Vandhunden
Vandhunden

Reputation: 426

Destruction of class members when destructor is not called

In the following code, when ptr is deleted, the destructor for Base is called, but not the destructor for Derived (due to destructor of Base not being virtual).

class Base
{
  int b;
};

class Derived : public Base
{
  int d;
};

int main(void)
{
    Base * ptr = new Derived();
    delete ptr;
    return 0;
}

Valgrind reports that the program contains no memory leaks, which i guess is true in the sense that all newed data is deleted in this particular case. My question is - given that the (default) destructor of Derived is not called, when and how is the memory for d deallocated or reclaimed?

Upvotes: 6

Views: 308

Answers (3)

Roman Saveljev
Roman Saveljev

Reputation: 2594

As other great guys mentioned, the standard says it is undefined behavior, but usually amongst compilers that care about competition and users this is up to system allocator implementation, which can be different from platform to platform. The destructor itself does not free the memory of Derived object, which contains fields.

When you call new Derived, global implementation of operator new is called and it receives number of bytes to allocate. It will be sizeof(Derived) in your case.

Upon actual memory freeing (global operator delete), allocator will know how many bytes to free from the address of the object being freed. So, the memory used by both b and d will be reclaimed

Upvotes: 1

Mats Petersson
Mats Petersson

Reputation: 129524

Calling the incorrect destructor, I think, is undefined behaviour. You should have a virtual destructor.

However, since the allocation is done in one block for the Derived class, it "works" because the internals of delete simply keeps track of the size of the allocation, and thus frees the 8 bytes that the object takes up, instead of the four that Base would use.

Note that the virtual destructor is not responsible in itself of FREEING the memory that this points to. That happens in delete after the destructor has been called.

Upvotes: 2

Alok Save
Alok Save

Reputation: 206646

It is Undefined behavior to call delete on a base class pointer pointing to a derived class object if the destructor in base class is not virtual.

Undefined behavior means that anything can happen. Whether memory leaks or not is irrelevant the fact is that your program can show any behavior and you cannot rely on any behavior that is shown.

For your code to be valid the destructor in Base class must be virtual.


C++11 Standard 5.3.5 Delete:
Para 3:

In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

Upvotes: 8

Related Questions