Reputation: 2218
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
Reputation: 124642
You're over thinking it. If you dereference a pointer which has already been delete
ed 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
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
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