我剛問過this question。簡而言之,當你從一個win32定時器回調中拋出時,這個異常不會出現在任何地方。它似乎在某處被Windows悄悄地處理。爲什麼我的析構函數在從win32定時器回調中拋出時調用?
好吧,這是一個問題。問題的另一方面是當拋出這個異常時,析構函數似乎不會被調用。在下面的代碼中,對於CFoo的std::vector
,輸出「〜CFoo」唯一的時間是當GetFooVect中的臨時對象被破壞並且rValue被複制到fooVect時。 fooVect的內容不會被破壞。
這是我最糟糕的噩夢。我非常使用RAII。我非常依賴我的析構函數進行適當的清理。
class CFoo
{
public:
~CFoo() {printf(__FUNCTION__ "\n");}
};
std::vector<CFoo> GetFooVect()
{
std::vector<CFoo> rValue;
rValue.push_back(CFoo());
rValue.push_back(CFoo());
rValue.push_back(CFoo());
return rValue;
}
VOID CALLBACK Timer(HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime)
{
// My destructors aren't called?
std::vector< CFoo> fooVect = GetFooVect();
// I'm destroyed
CFoo aFoo;
throw FooExcept();
printf("Also Here\n");
}
我試着通過簡單地拋出/捕獲C++異常重塑這種(即去除的Win32計時器回調變量)和Cfoo的的自毀蠻好的載體。出於某種原因,析構函數在這裏不會被稱爲向量中的東西。是什麼賦予了?這是否有一個合理的解釋,或者這是否奇怪,或兩者兼而有之?
+1:永遠不會從Win32回調或針對該問題的COM接口方法拋出異常;這樣做基本上是未定義的行爲。如果您在其中任何一箇中使用異常,請在返回之前捕獲*所有內容*,然後返回正常的返回碼。如果你希望異常傳播得更高,那麼你可以在其他地方保存狀態,通過API正常返回,然後檢查錯誤並在控制返回到自己的代碼時再次拋出... – BrendanMcK 2012-01-18 01:52:27
可能這裏發生了什麼是C++運行時在其異常實現中使用較低級的結構化異常處理(SEH)功能,而Win32中的代碼也使用SEH,但出於其自身目的干擾C++運行時。它比C++少C++,因此實現異常的C++運行時僅對編譯的代碼或編譯器附帶的庫具有「管轄權」; Win32代碼模塊和DLL是他們自己的宇宙。同樣,你只能在你自己的代碼中使用C++ RTTI,而不能使用從Win32或COM中獲取的任意對象。 – BrendanMcK 2012-01-18 02:03:07
要清楚,因此析構函數在運行時找到一個C++ catch塊時纔會執行 - 當然,在定時器回調之上的callstack中沒有更高的析構函數。 – 2012-01-18 16:42:17