2

这是一个基于真实问题的虚构场景。如果我有一个基类:

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

和一个派生类:

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;
};

然后说我有一个线程定期调用 Vehicle::run() 。我有另一个线程最终删除了指向汽车的指针。销毁顺序将导致汽车先被删除,然后是车辆。

如果线程(位于 Vehicle 对象中)在析构函数在 car 中运行之后(但显然在车辆被破坏之前)调用 incrementStuff 函数会发生什么?是否会执行 Car::incrementStuff 并尝试取消引用已删除的指针?还是会调用 Vehicle::incrementStuff ,它是安全的并且什么都不做?

假设当 Car::~Car() 正在运行时线程不能调用 Car::incrementStuff(这是由互斥锁阻止的)。

这段代码已被重构以避免这种情况,但我只是想知道是否有人可以阐明它是如何工作的,或者它是否只是简单的未定义行为?

更一般地说,如果我在 Car 被销毁但在 Vehicle 被销毁之前尝试调用 Car::incrementStuff 会发生什么?NULL 检查会起作用,还是该内存已经被释放并且现在可以被任何东西使用?或者,在基础对象被破坏之前,该内存不会“释放”?

4

3 回答 3

6

如果您已删除该Car对象,则后续调用incrementStuff()是未定义的行为。

顺便说一句,您可能应该在您的Vehicleclass中创建析构函数virtual。请参阅:何时使用虚拟析构函数?

于 2013-01-15T22:31:51.467 回答
4

你想多了。如果你取消引用一个已经被delete编辑的指针,你会调用未定义的行为。这就是你真正需要知道的。只要你打电话delete ptr; ptr无效。

同步访问此对象。

于 2013-01-15T22:26:14.423 回答
2

一个线程正在读取一个值,而另一个线程正在写入它。这是一场数据竞赛。如果两个动作未正确同步,则行为未定义。

于 2013-01-15T22:36:35.380 回答