[英]Why destructor is not called on exception?
我希望在這個程序中調用A::~A()
,但它不是:
#include <iostream>
struct A {
~A() { std::cout << "~A()" << std::endl; }
};
void f() {
A a;
throw "spam";
}
int main() { f(); }
但是,如果我將最后一行更改為
int main() try { f(); } catch (...) { throw; }
然后A::~A()
被調用。
我正在使用 Visual Studio 2005 的“Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86”進行編譯。命令行是cl /EHa my.cpp
。
編譯器正常嗎? 標准在這件事上是怎么說的?
析構函數沒有被調用,因為在堆棧展開之前調用了未處理異常的 terminate()。
C++ 規范所說的具體細節超出了我的知識范圍,但 gdb 和 g++ 的調試跟蹤似乎證實了這一點。
9 If no matching handler is found in a program, the function terminate() (_except.terminate_) is called. Whether or not the stack is unwound before calling terminate() is implementation-defined.
C++ 語言規范指出:為在從 try 塊到 throw 表達式的路徑上構造的自動對象調用析構函數的過程稱為“堆棧展開”。 您的原始代碼不包含 try 塊,這就是不會發生堆棧展開的原因。
抱歉,我沒有標准的副本。
我肯定想要一個明確的答案,所以有標准副本的人想要分享關於正在發生的事情的章節:
根據我的理解,終止僅稱為 iff:
在第二個示例中,dtor 在離開 try{} 塊時被調用。
在第一個示例中,當程序在離開 main() 函數后關閉時調用 dtor ---此時 cout 可能已經被銷毀。
我也假設編譯器不會生成相對於“a”的代碼,因為它沒有被引用,但仍然不是正確的行為,因為析構函數做了一些必須執行的事情。
因此,我在 VS2008/vc9 (+SP1) 中嘗試了調試和發布,並在拋出異常后調用 ~A,退出 f() - 如果我是對的,這是正確的行為。
現在我只是嘗試使用 VS2005/vc8 (+SP1) 並且它的行為相同。
我使用斷點來確定。 我剛剛檢查了控制台,我也收到了“~A”消息。 也許你在其他地方做錯了?
這個問題很容易用谷歌搜索,所以我在這里分享我的情況。
確保您的例外不跨越extern "C"
邊界或使用 MSVC 選項 /EHs(Enable C++ exeptions = Yes with Extern C functions (/EHs))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.