dag
dag

Reputation: 2218

Behavior when deleting derived object

This is a made-up scenario based off a real issue. If I have a base class:

class Vehicle
{
public:
     void run() { incrementStuff(); }
     virtual void incrementStuff() { } 
};

And a derived class:

class Car : public Vehicle
{
public:
     Car() : Vehicle() { stuff = new StuffClass(); }
     ~Car()  { delete stuff; stuff = NULL; }

     virtual void incrementStuff() { if (stuff != NULL) stuff->increment(); } 

protected:
     StuffClass* stuff;
};

Then say I have a thread which calls Vehicle::run() periodically. I have another thread that eventually deletes the pointer to car. The order of destruction will cause car to be deleted first, then vehicle.

What happens if the thread (living in the Vehicle object) calls the incrementStuff function AFTER the destructor has run in car (but obviously before vehicle has been destructed)? Will the Car::incrementStuff be executed and try to dereference an already deleted pointer? Or will the Vehicle::incrementStuff be called which is safe and does nothing?

Assume that the thread cannot call into Car::incrementStuff while Car::~Car() is running (this is prevented by a mutex).

This code has been refactored to avoid this, but I was just wondering if anyone can shed some light onto how this works, or if it is just plain undefined behavior?

More generally, what happens if I try to call Car::incrementStuff after Car has been destructed but before Vehicle has been? Will the NULL check work, or is that memory already deallocated and could be used by anything now? Or is that memory not 'freed' until the base object has been destructed?

Upvotes: 2

Views: 126

Answers (3)

Ed Swangren
Ed Swangren

Reputation: 124642

You're over thinking it. If you dereference a pointer which has already been deleteed you invoke undefined behavior. That's all you really need to know. As soon as you call delete ptr; ptr is invalid.

Synchronize access to this object.

Upvotes: 4

Pete Becker
Pete Becker

Reputation: 76245

One thread is reading a value while another thread is writing it. This is a data race. If the two actions are not properly synchronized the behavior is undefined.

Upvotes: 2

Steve
Steve

Reputation: 7271

If you've deleted the Car object then subsequent calls to incrementStuff() are undefined behaviour.

As an aside, you should probably make the destructor in your Vehicle class virtual. See: When to use virtual destructors?

Upvotes: 6

Related Questions