2011-11-01 74 views
1

在C++中,如何在我的析構函數體中檢測堆棧是否因拋出異常而解開?一旦檢測到,我可以獲得對活動異常的引用嗎?如何在析構函數中檢測異常是否處於活動狀態?

我問,因爲我想添加一些調試代碼,解釋爲什麼會出現某種情況以及是否由於例外。

+3

這聽起來像是現在是閱讀[GoTW#47](http://www.gotw.ca/gotw/047.htm)的好時機。 –

+0

建設可能會失敗,但破壞永遠不會。在對象銷燬期間沒有任何異常處理機制。 – Mahesh

+1

@Mahesh我認爲你誤解了這個問題。它不是關於析構函數中的異常處理,而是關於檢測析構函數是否因對象的周圍範圍中拋出的異常而被調用。 –

回答

4

std::uncaught_exception告訴你堆棧是否因拋出異常而解開,這就是你所問的。

但是,它並沒有告訴你你可能想知道的內容:你調用它的析構函數的對象是否在正在解開的堆棧的一部分中,或者是正常銷燬的那部分堆棧由於非異常退出一些其他的析構函數是開卷的一部分下方的範圍:

struct A { 
    ~A(); 
}; 

struct B { 
    ~B(); 
} 

int main() { 
    try { 
     A a; 
     throw 1; 
    } catch(...) {} 
} 

A::~A() { 
    std::uncaught_exception(); // true 
    B b; 
} 

B::~B() { 
    std::uncaught_exception(); // also true, but "b" isn't being "unwound", 
     // because ~A() returned, it didn't throw. 
} 

相反的是DeadMG和XEO說,你不能去尚未捕獲的異常的參考。不帶操作數的throw會重新拋出「當前處理的異常」,也就是說,您所在的catch處理程序或其捕獲處理程序已調用您的異常。它不會重新拋出未捕獲的異常。

+0

這就是我認爲扔不工作,感謝確認。 – WilliamKF

+0

「_whether **由於異常被拋出,正在解除**堆棧_」嗯,有時確實有兩個**堆棧:一個解開,一個對象的析構函數使用的堆棧被破壞**因爲**的展開。 – curiousguy

0

在C++中,如何檢測我的析構函數體是否由於引發異常而導致堆棧被解除?

不是。

一旦檢測到,我可以獲得對活動異常的引用嗎?

0

有一個std::uncaught_exception()功能。但是,嘗試訪問異常對象可以做的唯一有用的事情是重新拋出它並嘗試捕獲它。一般來說,你絕不應該從任何析構函數中拋出異常。

+0

如何重新拋出未被捕獲的異常? – WilliamKF

+0

'try {throw; } catch(std :: exception const&e){/ *處理它* /}' – Xeo

+0

「_There是一個std :: uncaught_exception()函數._」不回答問題。 – curiousguy

相關問題