這是一個基於真正問題的構建方案。如果我有一個基類:刪除派生對象時的行爲
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;
};
然後說我有一個要求車輛:: run()的定期線程。我有另一個線程,最終刪除指向汽車的指針。銷燬順序將導致車輛首先被刪除,然後車輛被刪除。
如果線程(生活在Vehicle對象中)調用析構函數在汽車中運行後(但顯然在車輛被破壞之前)調用incrementStuff函數會發生什麼? Car :: incrementStuff是否會被執行並嘗試解引用已經被刪除的指針?或者將調用Vehicle :: incrementStuff,這是安全的,什麼都不做?
假設當Car ::〜Car()正在運行時,線程無法調用Car :: incrementStuff(這是由互斥鎖阻止的)。
此代碼已被重構,以避免這種情況,但我只是想知道是否有人可以闡明這是如何工作的,或者如果它只是普通的未定義行爲?
更一般地說,如果我在Car被破壞之後但在Vehicle之前嘗試致電Car :: incrementStuff,會發生什麼? NULL檢查是否工作,或者內存已經釋放,現在可以被任何東西使用?或者,在基礎對象被破壞之前,內存是不是「釋放」的?