Structured Exception Handling (C/C++)
結構化例外狀況處理 (SEH) 是 C 和 C++ 的 Microsoft 延伸模組,可處理某些例外程式碼情況,例如硬體錯誤,正常運作。 雖然 Windows 和 Microsoft C++ 支援 SEH,但建議您在 C++ 程式碼中使用 ISO 標準 C++ 例外狀況處理。 它可讓您的程式碼更具可攜性和彈性。 不過,若要維護現有的程式碼或特定種類的程式,您可能仍必須使用 SEH。
Microsoft 特定:
文法
try-except-statement
:
__try
compound-statement
__except
(
filter-expression
)
compound-statement
try-finally-statement
:
__try
compound-statement
__finally
compound-statement
備註
使用 SEH,您可以確保資源,例如記憶體區塊和檔案,如果執行意外終止,就會正確釋放。 您也可以使用不依賴 goto
語句的精簡結構化程式碼,或詳細測試傳回碼,來處理特定問題,例如記憶體不足。
try-except
本文中提到的 和 try-finally
語句是 C 和 C++ 語言的 Microsoft 延伸模組。 它們支援 SEH,讓應用程式在終止執行的事件之後取得程式的控制權。 雖然 SEH 與 C++ 原始程式檔搭配運作,但它不是專為 C++ 所設計。 如果您在使用 或 /EHsc
選項編譯 /EHa
的 C++ 程式中使用 SEH,則會呼叫本機物件的解構函式,但其他執行行為可能不是您預期的行為。 如需圖例,請參閱本文稍後的範例。 在大部分情況下,我們建議您使用 ISO 標準 C++ 例外狀況處理 ,而不是 SEH。 使用 C++ 例外狀況處理,確保您的程式碼更具可攜性,而且您可以處理任何類型的例外狀況。
如果您有使用 SEH 的 C 程式碼,您可以將它與使用 C++ 例外狀況處理的 C++ 程式碼混合。 如需詳細資訊,請參閱 處理 C++ 中的結構化例外狀況。
有兩種 SEH 機制:
例外狀況 處理常式或
__except
區塊,可根據值回應或關閉例外狀況filter-expression
。 如需詳細資訊,請參閱try-except
語句 。無論例外狀況是否造成終止,一律呼叫的終止處理常式 或
__finally
區塊。 如需詳細資訊,請參閱try-finally
語句 。
這兩種處理常式是不同的,但透過稱為 回溯堆疊 的程式密切相關。 發生結構化例外狀況時,Windows 會尋找目前使用中的最新安裝例外狀況處理常式。 處理常式可以執行下列三項事項的其中一項:
無法辨識例外狀況,並將控制權傳遞至其他處理常式 (
EXCEPTION_CONTINUE_SEARCH
)。辨識例外狀況,但關閉例外狀況(
EXCEPTION_CONTINUE_EXECUTION
)。辨識例外狀況並加以處理(
EXCEPTION_EXECUTE_HANDLER
)。
可辨識例外狀況的例外狀況處理常式可能不在例外狀況發生時正在執行的函式中。 它可能位於堆疊上較高的函式中。 目前執行中函式和堆疊框架上的所有其他函式都會終止。 在此程式中,堆疊會 解除復原 。 也就是說,已終止函式的局部非靜態變數會從堆疊中清除。
回溯堆疊時,作業系統會呼叫您為每個函式所撰寫的任何終止處理常式。 藉由使用終止處理常式,您可以清除因為異常終止而保持開啟的資源。 如果您已輸入重要區段,您可以在終止處理常式中結束它。 當程式即將關閉時,您可以執行其他管家工作,例如關閉和移除暫存檔。
下一步
範例
如先前所述,如果您在 C++ 程式中使用 SEH,並使用 或 /EHsc
選項加以編譯 /EHa
,則會呼叫本機物件的解構函式。 不過,如果您在使用 C++ 例外狀況時,執行期間的行為可能不是您預期的行為。 此範例示範這些行為差異。
#include <stdio.h>
#include <Windows.h>
#include <exception>
class TestClass
{
public:
~TestClass()
{
printf("Destroying TestClass!\n");
}
};
__declspec(noinline) void TestCPPEX()
{
#ifdef CPPEX
printf("Throwing C++ exception\n");
throw std::exception("");
#else
printf("Triggering SEH exception\n");
volatile int *pInt = 0x00000000;
*pInt = 20;
#endif
}
__declspec(noinline) void TestExceptions()
{
TestClass d;
TestCPPEX();
}
int main()
{
__try
{
TestExceptions();
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
printf("Executing SEH __except block\n");
}
return 0;
}
如果您使用 /EHsc
來編譯此程式碼,但未定義本機測試控制項宏 CPPEX
, TestClass
解構函式不會執行。 輸出如下所示:
Triggering SEH exception
Executing SEH __except block
如果您使用 /EHsc
來編譯器代碼並使用 CPPEX
來定義 /DCPPEX
(因此擲回 C++ 例外狀況), TestClass
解構函式會執行,而輸出看起來如下:
Throwing C++ exception
Destroying TestClass!
Executing SEH __except block
如果您使用 /EHa
編譯器代碼, TestClass
解構函式會執行是否使用標準 C++ throw
運算式或使用 SEH 擲回例外狀況。 也就是說,是否 CPPEX
定義 。 輸出如下所示:
Throwing C++ exception
Destroying TestClass!
Executing SEH __except block
如需詳細資訊,請參閱 /EH
(例外狀況處理模型)。
END Microsoft 特定
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應