Информация об изменениях

Сообщение Виртуальные деструкторы при нестандартном управлении памятью от 28.03.2022 8:23

Изменено 28.03.2022 9:07 Ester

Виртуальные деструкторы при нестандартном управлении памятью
Это сообщение — комментарий к странице "Deep C++ > А чисто виртуальные деструкторы — бывают?", но она закрыта? (

У многих компиляторов вызов виртуальных деструкторов при нестандартном управлении памятью происходит неправильно. cl выдержал все проверки, только со второй формой оператора delete, по видимости, есть некоторые проблемы:
  Текст virtual destructors.cpp
#include <stddef.h>
#include <stdio.h>

class A {
    int ma;
public:
    A ();
    virtual ~A ();
    void *operator new (size_t size);
    void operator delete (void *p, size_t size);
    void *operator new [] (size_t size) { return operator new (size); }
    void operator delete [] (void *p, size_t size) { operator delete (p, size); }
};

class B : public A {
    int mb;
public:
    B ();
    virtual ~B ();
};

int main ()
{
    A *pa = new B;
    delete pa;
    A *paa = new B [2];
    delete [] paa;
    return 0;
}

A::A  () { printf ("A::A()\n"); }
B::B  () { printf ("B::B()\n"); }
A::~A () { printf ("A::~A()\n"); }
B::~B () { printf ("B::~B()\n"); }

void* A::operator new (size_t size) 
{
    void *p;
    p = ::operator new (size);
    printf ("A::operator new (%u) = <%08x>\n", size, p);
    return p;
}

void A::operator delete (void *p, size_t size)
{
    ::operator delete (p);
    printf ("A::operator delete (<%08x>, %u)\n", p, size);
}

Результаты работы:
  Результаты
Оптимизирующий 32-разрядный компилятор Microsoft (R) C/C++ версии 16.00.30319.01 для 80x86:
A::operator new (12) = <00334fc8>
A::A()  B::B ()  B::~B ()  A::~A()
A::operator delete (<00334fc8>, 12)
A::operator new (28) = <003328b8>
A::A ()  B::B ()  A::A ()  B::B ()
B::~B()  A::~A()  B::~B()  A::~A()
A::operator delete (<003328b8>, 12)

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86:
A::operator new (12) = <00332bc8>
A::A()  B::B() B::~B() A::~A()
A::operator delete (<00332bc8>, 12)
A::operator new (28) = <00332be0>
A::A ()  B::B ()  A::A ()  B::B ()
B::~B()  A::~A()  B::~B()  A::~A()
A::operator delete (<00332be0>, 12)

Intel(R) C++ Compiler for 32-bit applications, Version 9.0:
A::operator new (12) = <00333db8>
A::A()  B::B()  B::~B()  A::~A()
A::operator delete (<00333db8>, 12)
A::operator new (28) = <00332bb0>
A::A()  B::B()  A::A()  B::B()  A::~A()  A::~A()
A::operator delete (<00332bb0>, 0)

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland:
A::operator new (12) = <00852d14>
A::A()  B::B()  B::~B()  A::~A()
A::operator delete (<00852d14>, 12)
A::operator new (28) = <00852d14>
A::A()  B::B()  A::A()  B::B()  A::~A()  A::~A()
A::operator delete (<00852d14>, 16)

Borland C++ 5.0 Copyright (c) 1987, 1996 Borland International:
A::operator new (6) = <00000e42>
A::A()  B::B()  B::~B()  A::~A()
A::operator delete (<00000e42>, 6)
A::operator new (16) = <00000e42>
A::A ()  B::B ()  A::A ()  B::B ()
A::~A()  A::~A()  A::~A()  A::~A()
A::operator delete (<00000e42>, 8)

Borland C++  Version 3.1 Copyright (c) 1992 Borland International
A::operator new (6) = <000005e2>
A::A()  B::B()  B::~B()  A::~A()
A::operator delete (<000005e2>, 6)
A::A()  B::B()  A::A()  B::B()  A::~A()  A::~A()


Borland провалился, даже у Intel 9 версии ошибки.

При современной технике программирования деструкторы следует объявлять виртуальными всегда.
c++
Виртуальные деструкторы при нестандартном управлении памятью
Это сообщение — комментарий к странице "Deep C++ > А чисто виртуальные деструкторы
Автор: Павел Кузнецов
Дата: 03.04.03
— бывают?"
, но она закрыта? (

У многих компиляторов вызов виртуальных деструкторов при нестандартном управлении памятью происходит неправильно. cl выдержал все проверки, только со второй формой оператора delete, по видимости, есть некоторые проблемы:
  Текст virtual destructors.cpp
#include <stddef.h>
#include <stdio.h>

class A {
    int ma;
public:
    A ();
    virtual ~A ();
    void *operator new (size_t size);
    void operator delete (void *p, size_t size);
    void *operator new [] (size_t size) { return operator new (size); }
    void operator delete [] (void *p, size_t size) { operator delete (p, size); }
};

class B : public A {
    int mb;
public:
    B ();
    virtual ~B ();
};

int main ()
{
    A *pa = new B;
    delete pa;
    A *paa = new B [2];
    delete [] paa;
    return 0;
}

A::A  () { printf ("A::A()\n"); }
B::B  () { printf ("B::B()\n"); }
A::~A () { printf ("A::~A()\n"); }
B::~B () { printf ("B::~B()\n"); }

void* A::operator new (size_t size) 
{
    void *p;
    p = ::operator new (size);
    printf ("A::operator new (%u) = <%08x>\n", size, p);
    return p;
}

void A::operator delete (void *p, size_t size)
{
    ::operator delete (p);
    printf ("A::operator delete (<%08x>, %u)\n", p, size);
}

Результаты работы:
  Результаты
Оптимизирующий 32-разрядный компилятор Microsoft (R) C/C++ версии 16.00.30319.01 для 80x86:
A::operator new (12) = <00334fc8>
A::A()  B::B ()  B::~B ()  A::~A()
A::operator delete (<00334fc8>, 12)
A::operator new (28) = <003328b8>
A::A ()  B::B ()  A::A ()  B::B ()
B::~B()  A::~A()  B::~B()  A::~A()
A::operator delete (<003328b8>, 12)

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86:
A::operator new (12) = <00332bc8>
A::A()  B::B() B::~B() A::~A()
A::operator delete (<00332bc8>, 12)
A::operator new (28) = <00332be0>
A::A ()  B::B ()  A::A ()  B::B ()
B::~B()  A::~A()  B::~B()  A::~A()
A::operator delete (<00332be0>, 12)

Intel(R) C++ Compiler for 32-bit applications, Version 9.0:
A::operator new (12) = <00333db8>
A::A()  B::B()  B::~B()  A::~A()
A::operator delete (<00333db8>, 12)
A::operator new (28) = <00332bb0>
A::A()  B::B()  A::A()  B::B()  A::~A()  A::~A()
A::operator delete (<00332bb0>, 0)

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland:
A::operator new (12) = <00852d14>
A::A()  B::B()  B::~B()  A::~A()
A::operator delete (<00852d14>, 12)
A::operator new (28) = <00852d14>
A::A()  B::B()  A::A()  B::B()  A::~A()  A::~A()
A::operator delete (<00852d14>, 16)

Borland C++ 5.0 Copyright (c) 1987, 1996 Borland International:
A::operator new (6) = <00000e42>
A::A()  B::B()  B::~B()  A::~A()
A::operator delete (<00000e42>, 6)
A::operator new (16) = <00000e42>
A::A ()  B::B ()  A::A ()  B::B ()
A::~A()  A::~A()  A::~A()  A::~A()
A::operator delete (<00000e42>, 8)

Borland C++  Version 3.1 Copyright (c) 1992 Borland International
A::operator new (6) = <000005e2>
A::A()  B::B()  B::~B()  A::~A()
A::operator delete (<000005e2>, 6)
A::A()  B::B()  A::A()  B::B()  A::~A()  A::~A()


Borland провалился, даже у Intel 9 версии ошибки.

При современной технике программирования деструкторы следует объявлять виртуальными всегда.
c++