2011-09-06 16 views
4

考慮一下:展開期間投擲 - 此示例爲何起作用?

void thrower() { 
    throw "123"; 
} 

struct Catcher { 
    ~ Catcher() { 
     try {thrower();} 
     catch (...) {} 
    } 
}; 

int main() { 
    try { 
     Catcher c; 
     throw 1.23; 
    } 
    catch (...) {} 
} 

這編譯時和未GCC 4.3打電話terminate運行,但according to the standard(15.5.1)

...當異常處理機制,完成後評價表達式被拋出,但在捕獲異常之前(15.1),調用通過未捕獲的異常退出的用戶函數... terminate應該被調用。

當雙已被拋出之後~Catcher被調用,這是「在完成評估後...前的異常被捕獲」和thrower是,這種滿足「其經未捕獲的異常退出用戶功能」上述條件。是的,char*被捕獲,但之後只有用戶函數退出。

應該不是terminate

爲了強調這一點:

void do_throw() { 
    throw "123"; 
} 

void thrower() { 
    do_throw(); 
    // Uncaught exception here (A) 
} 

struct Catcher { 
    ~ Catcher() { 
     try {thrower(); /* (B) */} 
     catch (...) {} 
    } 
}; 

int main() { 
    try { 
     Catcher c; 
     throw 1.23; 
    } 
    catch (...) {} 
} 

(A)發生在(B),其已在進步異常的情況下。

那麼,不應該terminate被稱爲?如果不是,這是一個法律情況,我們可以同時出現兩個例外情況,我們在哪裏畫線?

回答

3

不同強調:

異常處理機制,完成表達的評估之後被拋出,但異常之前被捕獲(15.1),調用經由退出的用戶功能未捕獲的異常...終止應稱爲

thrower()是一個用戶函數,它通過異常退出,但它不被異常處理機制調用;它是由本身由異常處理機制稱爲另一個用戶函數(Catcher的析構函數),並且該函數確實經由例外不出口調用。

4

爲什麼terminate被調用?您有一個catch(...)區塊,它捕獲所有例外情況:捕獲doublemain中的一個)和一個捕獲char const[4]~Catcher中的那個)。

因此,沒有函數「以未捕獲的異常退出」,因爲所有異常都被捕獲。

這裏的關鍵詞是「調用終止未捕獲的異常的用戶函數」。這與不是相同,「調用一個用戶函數,該函數在該行的某個地方調用一個以未捕獲的異常終止的用戶函數」。如果你調用一個函數,並且它有一個try/catch塊,然後在那裏你調用一些函數,這個函數以異常結束,但是你發現異常,terminate不被調用。

TL;博士:在調用層次結構異常的評價之間,以及捕獲必須用一個異常退出的terminate之前發起第一個呼叫被調用,第一次調用下面未分支機構。這是有道理的,因爲您無法設置另一個catch塊之間的區塊之間的時間被拋出的對象被評估和它被捕獲。

+0

他問的問題是,在1.23被拋出,尚未抓到,另一項功能叫做拋出123不是由函數本身抓獲。所以根據標準,終止應該被調用。 – Shahbaz

+0

@shabaz更新。 –

0

這是完全合法的代碼。在捕捉引發問題之前所發生的一切。 只有當您移除〜Catcher中的try/catch時,纔會在放卷期間拋出異常。

3

哪個函數,由異常處理機制調用,通過 未捕獲的異常退出。由異常處理此機制 調用的唯一功能是Catcher::~Catcher(),它正常退出,由 到達函數的結尾。

還有根本沒有限制的同時 活躍異常的數目。限制是必須在特定點上傳播的例外數量。如果Catcher::~Catcher()通過一個異常退出 ,我們將有兩個例外傳播起來,在一個 由此引發的析構函數的調用,並通過該 析構函數退出的一個。只要析構函數捕獲所有異常,並且不會傳播它們,則不存在任何問題。

3

...當異常處理機制,完成表達的評價 後拋出,但異常被捕獲 (15.1)之前,調用通過一個未捕獲的異常退出用戶功能... 終止應被調用。

異常處理機制調用~Catcher(),它不會通過未捕獲的異常退出;因此它不叫std::terminate。它不直接呼叫thrower()

+0

'捕手'不會通過一個未捕獲的異常退出,但'投擲者' – spraff

+0

這聽起來是正確的。 「調用函數」不是遞歸定義的,它只是指當前的上下文。 –

+0

@spraff:是的,但異常處理機制不會調用'thrower()'。它只調用'〜Catcher()'。 –