try-except
陳述式
try-except
語句是 Microsoft 特定的 擴充功能,可支援 C 和 C++ 語言中的結構化例外狀況處理。
// . . .
__try {
// guarded code
}
__except ( /* filter expression */ ) {
// termination code
}
// . . .
文法
try-except-statement
:
__try
compound-statement
__except (
expression
)
compound-statement
備註
語句 try-except
是 C 和 C++ 語言的 Microsoft 延伸模組。 它可讓目標應用程式控制通常終止程式執行的事件。 這類事件稱為 結構化例外狀況 ,或 簡短的例外狀況 。 處理這些例外狀況的機制稱為 結構化例外狀況處理 (SEH)。
如需相關資訊,請參閱 try-finally 語句 。
例外狀況可能是硬體型或軟體型。 即使應用程式無法從硬體或軟體例外狀況完全復原,結構化例外狀況處理也很有用。 SEH 可讓您顯示錯誤資訊,並捕捉應用程式的內部狀態,以協助診斷問題。 對於不容易重現的間歇性問題特別有用。
注意
結構化例外狀況處理可搭配 Win32 處理 C 和 C++ 原始程式檔。 不過,它並非特別針對 C++ 所設計。 使用 C++ 例外狀況處理可確保您的程式碼更具可移植性。 此外,C++ 例外狀況處理更有彈性,因為它可以處理任何類型的例外狀況。 針對 C++ 程式,建議您使用原生 C++ 例外狀況處理: try、catch 和 throw 語句。
子句之後 __try
的複合陳述式是 主體 或 受防護區 段。 運算式 __except
也稱為 篩選 運算式。 其值會決定如何處理例外狀況。 __except
子句後面的複合陳述式則是例外狀況處理常式。 處理常式會指定在主體區段執行期間引發例外狀況時要採取的動作。 執行程序如下所示:
執行保護的區段。
如果執行保護的區段時未發生例外狀況,則會在
__except
子句之後的陳述式繼續執行。如果在受防護區段執行期間發生例外狀況,或在受防護區段呼叫的任何常式中,則會
__except
評估運算式。 有三個可能的值:EXCEPTION_CONTINUE_EXECUTION
(-1)例外狀況已關閉。 在例外狀況發生的位置繼續執行。EXCEPTION_CONTINUE_SEARCH
(0) 無法辨識例外狀況。 繼續搜尋處理常式的堆疊,先搜尋包含try-except
語句,然後再搜尋優先順序為下一個最高優先順序的處理常式。EXCEPTION_EXECUTE_HANDLER
(1) 已辨識例外狀況。 藉由執行__except
複合陳述式,將控制權傳送至例外狀況處理常式,然後在 區塊之後__except
繼續執行。
運算式 __except
會評估為 C 運算式。 限制為單一值、條件運算式運算子或逗號運算子。 如果需要更廣泛的處理,運算式可以呼叫常式,傳回上面所列三個值的其中一個。
每個應用程式都有自己的例外狀況處理常式。
跳入 __try
語句無效,但跳出語句無效。 如果在執行 try-except
語句的過程中終止進程,則不會呼叫例外狀況處理常式。
為了與舊版相容,_try、_except和_leave 是 、 __except
和 的 __try
同義字, __leave
除非指定編譯器選項 /Za (停用語言延伸模組)。
__leave
關鍵字
__leave
關鍵字只有在語句的 try-except
受防護區段中才有效,其效果是跳到受防護區段的結尾。 然後在例外狀況處理常式之後的第一個陳述式繼續執行。
goto
語句也可以跳出受防護的區段,而且不會降低效能,就像在 try-finally 語句中 一樣。 這是因為不會發生堆疊回溯。 不過,我們建議您使用 __leave
關鍵字,而不是 goto
語句。 原因是,如果受防護的區段很大或很複雜,您不太可能犯程式設計錯誤。
結構化例外狀況處理內建函式
結構化例外狀況處理提供兩個可用於 語句的內部 try-except
函數: GetExceptionCode 和 GetExceptionInformation 。
GetExceptionCode
會傳回例外狀況的程式碼(32 位整數)。
內建函式 GetExceptionInformation
會傳回EXCEPTION_POINTERS 結構的指標 ,其中包含例外狀況的其他資訊。 透過這個指標就可以存取發生硬體例外狀況當時的電腦狀態。 結構如下所示:
typedef struct _EXCEPTION_POINTERS {
PEXCEPTION_RECORD ExceptionRecord;
PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
指標型 PEXCEPTION_RECORD
別和 PCONTEXT
定義于 include 檔案 < winnt.h > 中,且 _EXCEPTION_RECORD
_CONTEXT
定義于 include 檔案 < 摘錄.h 中。>
您可以在例外狀況處理常式內使用 GetExceptionCode
。 不過,您只能在例外狀況篩選運算式內使用 GetExceptionInformation
。 它指向的資訊通常是在堆疊上,當控制項傳送至例外狀況處理常式時,就無法再使用。
在終止處理常式內可以使用內部 函數 AbnormalTermination 。 如果 try-finally 語句的 主體循序終止,則會傳回 0。 在所有其他情況下,它會傳回 1。
<excpt.h > 會定義這些內建函式的一些替代名稱:
GetExceptionCode
相當於 _exception_code
GetExceptionInformation
相當於 _exception_info
AbnormalTermination
相當於 _abnormal_termination
範例
// exceptions_try_except_Statement.cpp
// Example of try-except and try-finally statements
#include <stdio.h>
#include <windows.h> // for EXCEPTION_ACCESS_VIOLATION
#include <excpt.h>
int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
puts("in filter.");
if (code == EXCEPTION_ACCESS_VIOLATION)
{
puts("caught AV as expected.");
return EXCEPTION_EXECUTE_HANDLER;
}
else
{
puts("didn't catch AV, unexpected.");
return EXCEPTION_CONTINUE_SEARCH;
};
}
int main()
{
int* p = 0x00000000; // pointer to NULL
puts("hello");
__try
{
puts("in try");
__try
{
puts("in try");
*p = 13; // causes an access violation exception;
}
__finally
{
puts("in finally. termination: ");
puts(AbnormalTermination() ? "\tabnormal" : "\tnormal");
}
}
__except(filter(GetExceptionCode(), GetExceptionInformation()))
{
puts("in except");
}
puts("world");
}
輸出
hello
in try
in try
in filter.
caught AV as expected.
in finally. termination:
abnormal
in except
world
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應