Weathered
Weathered

Reputation: 3

Why does calling the Base class destructor crash this program?

class ParentClass {
protected:
    int* intArray;

public:
    ~ParentClass(){
        delete [] intArray;
    }
};

class ChildClass : public ParentClass {
public:
    ChildClass() : ParentClass() {
        intArray = new int[5];
    }
};

int main(int argc, const char * argv[]) {
    ChildClass child;
    child.~ChildClass(); //This line crashes the program. why??
}

The specific error that it throws: initialization(37640,0x7fff78623300) malloc: * error for object 0x100100aa0: pointer being freed was not allocated * set a breakpoint in malloc_error_break to debug

The pointer is referencing intArray declared in ParentClass, the error states that the memory was not allocated, but it was allocated in the ChildClass constructor.

Can someone explain what process this is going through to generate this error?

Upvotes: 0

Views: 2182

Answers (3)

Tristan
Tristan

Reputation: 916

You are experiencing undefined behavior. From the C++ standard:

Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended (3.8). [Example: if the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined.

Upvotes: 1

Christophe
Christophe

Reputation: 73386

child is a local object of main(). It's automatically destroyed when leaving the scope of the function.

Unfortunately you manually destroy it before leaving the function by calling explicitly the detructor. So it gots destroyed two times (one too much) : the second times it crashes !

You don't have to destroy local objects. Explicit destruction is only needed for pointers when you allocate dynamically objects with new. But then you should delete them using delete.

The explicit call of the destructor is only relevant in a very rare case: when you want to reuse the storage of a dynamic object with a placement-new.

Remark: in ParentClass you should initialize intArray to nullptr. This would make sure that if accidentally no allocation would be done, delete wouldn't try to deallocate an unititalized pointer.

Upvotes: 0

Dai
Dai

Reputation: 155250

The problem isn't that intArray isn't allocated, it's that you're deallocating it twice.

ChildClass child; instantiates the ChildClass instance and calls the default constructor which allocates intArray fine, no problem there.

Then your code explicitly calls the destructor (something you generally never need to do for stack-allocated/automatic objects).

Then the compiler inserts another call to the destructor during scope cleanup, which causes delete[] to be called a second time, which is incorrect, and causes the crash. Your debugger probably reports the last line of the function (where your explicit destructor call is) when it really should point to the closing brace.

To be sure, set a breakpoint in your destructor and run your program and see how many times it's hit.

Upvotes: 2

Related Questions