我經歷了與當在程序退出的Visual C++運行時自毀我的對象,而惱人的問題絆倒了。的Visual C++運行時對象破壞秩序
我有被用來確保某些國家引用是有效的一類。我需要將狀態存儲一段未知的時間,在此期間狀態可以被銷燬,我不能使用shared_ptr
。所以我用
class MyClass
{
private:
static std::list<MyClass*> make_list();
static std::list<MyClass*> refed_list;
static void StateClosed(B* state);
public:
B* state;
MyClass(B* state);
virtual ~MyClass();
bool still_valid() const;
};
的MyClass
每個實例都增加了自己在其構造refed_list
,並在其析構函數刪除自身。如果封裝狀態爲關閉狀態,則MyClass
會得到通知,並會檢查refed_list
是否爲封裝實例並使其指針失效。這並不重要,重要的是它使用了一個static list
,它在構造函數/析構函數中訪問這個列表。我在定義了MyClass
的文件中初始化了refed_list
。
現在,問題..當我的程序關閉時,運行時會在某個時間點清除refed_list
,然後清除MyClass
的實例,調用它們的析構函數。然後他們嘗試訪問已被清理的refed_list
。這導致我的迭代器不正確,並且我得到未定義的行爲,在這種情況下調試斷言失敗。
有沒有解決這個問題的方法嗎?我懷疑我可以指定在不同編譯單元中的哪個訂單對象被銷燬,但是有沒有辦法檢查refed_list
是否仍然有效?目前我檢查是否refed_list.size() == 0
,它似乎工作,但這種行爲也是不明確的(我認爲?)。
聽起來像一個單身一輩子的問題。我認爲Scott Meyers或Andrei Alexandrescu寫了一些關於以三種不同方式管理他們的內容。鳳凰辛格爾頓可能會成爲你的衚衕。 – 2013-02-24 11:14:02
這是我爲什麼不允許我的團隊使用全局類實例的衆多原因之一。因爲在程序退出期間對象破壞的順序是非確定性的,或者很難正確確定。無論如何,在WinMain/main返回之前,你是否可以運行應用程序清除函數?或者更好的是,除非那些析構函數執行關鍵任務,爲什麼不在應用程序關閉時讓所有對象泄漏呢? – selbie 2013-02-24 11:45:38
@selbie我開始認爲這是一個好主意。我這樣做的原因是因爲我需要存儲一個在使用前可能會失效的對象,並且我不能使用'shared_ptr',所以我需要通知對象它們是否有效。因此,我需要跟蹤對象,這就是爲什麼我有靜態列表。但是,是的,如果我重寫一些東西,我可以手動關閉它,這應該可以解決我的問題。掛鉤進程有時會讓事情變得困難.. – user1520427 2013-02-24 21:47:17