2010-09-24 143 views

回答

19

你實際上有三種機制:

  • C++異常,由編譯器(try/catch
  • 結構化異常處理(SEH),Windows提供實現(__try/__except
  • MFC異常宏(TRY,CATCH - 建立在SEH/C++的異常之上 - 請參閱TheUndeadFish的評論)

C++異常通常保證在堆棧展開期間自動清理(即,本地對象的析構函數運行),其他機制不會。當他們被明確拋出

C++異常纔會發生。結構化例外可能發生在許多操作中,例如由於未定義的行爲,將無效指針傳遞給API,卸載內存映射文件的後備存儲等等。

MFC做了介紹異常宏以支持例外即使編譯器不執行。

+0

只是爲了好奇,MFC曾經打算在VC++以外的任何編譯器上工作? – 2010-09-24 13:49:51

+2

保證清理不需要C++異常。用/ EHa編譯。 – 2010-09-24 14:27:05

+0

MFC確實在Watcom C/C++ 10上工作。不知何故。沒有巫師和東西。 – peterchen 2010-09-24 14:28:59

6

A C++異常是編程語言C++的特徵。 結構化異常是Windows操作系統的不同概念。 這兩個使用類似的語法,但技術上不同。 Windows結構化異常不僅可用於C++,還可用於與C.

有時溶液統一兩者的處理:在Windows應用程序可以提供一個處理函數,其捕捉所有結構化異常並拋出C++異常(由你定義)。

4

兩者都提供錯誤發生時堆棧展開的機制。

結構化異常是由Windows提供,從內核的支持。如果您執行諸如訪問無效內存位置之類的操作,它們會被Windows引發。它們也用於支持自動堆棧增長等功能。它們本身很少使用,但C++,.NET和類似語言中的語言異常通常建立在它們之上。您使用特殊關鍵字__try__catch來處理這些例外情況。但是,處理它們相對比較困難且容易出錯,因爲可以打破自動堆棧擴展等功能,並且可能會破壞C++語言異常。

C++異常由C++語言指定。被拋出和被捕獲的數據類型是C++對象(包括原始類型的可能性)。編譯器和運行時在底層結構化異常機制之上實現了這些功能。如果您使用C++語言的try,catchthrow關鍵字,就會得到這個結果。

SEH異常具有比C++異常更多的功能,例如支持恢復和所謂的「向量」處理程序(它接收異常通知但不一定防止堆棧解除),但除非您明確知道您想要使用它們,我會避免它們。如果您的程序執行某些非法或未定義的操作,可能最常用的方法是使用MiniDumpWriteDump編寫故障轉儲。

1

C++異常將跨平臺工作。不幸的是,SEH將嚴格限制可移植性(除了可能跨越不同的Windows版本)。

而且SEH似乎捕捉到大量的原生Windows異常(如訪問衝突,被指定無效的句柄)等

7

這是一個沉重的實現細節,但在Windows C++異常也是一個SEH異常。異常代碼是0xE04D5343(最後三個字節='MSC')。並且所有常規的SEH支持都用於展開堆棧,獲取自動清理代碼以運行並過濾異常,以便選擇正確的catch子句。在過濾器表達式中獲取拋出的異常對象是由CRT添加超出SEH提供的管道。 SEH也支持__finally子句,但在標準C++中沒有使用。

另一個實現細節是/ EH編譯器設置。缺省值(/ EHsc)允許編譯器優化生成的代碼並抑制運行自動清理所需的異常過濾器。如果它可以看到沒有發出的C++代碼可以拋出異常。這首先是一個空間優化,一個用於x86代碼的小時間優化,但不適用於x64代碼。爲了自動清理SEH異常,必須使用/ EHa進行編譯,以便優化被抑制。

與SEH結合使用C++異常的一個好方法是使用_set_se_translator(),因此您可以將SEH異常轉換爲C++異常。儘管追查SEH例外情況並不明智,但它們幾乎總是令人討厭。

+0

__try/__除塊之外是否會捕獲所有SEH異常以及所有C++異常? – Alexandru 2014-03-19 03:04:40

+0

另外需要注意的是,根據MSDN,對於具有try塊的堆棧上的每個函數調用,僅調用_set_se_translator()一次,並且必須基於每個線程進行設置。 – Alexandru 2014-03-19 03:05:01

相關問題