try-except語句是一個Microsoft特定延伸模組,可支援 C 和 C++ 語言的結構化例外狀況處理。
// . . .
__try {
// guarded code
}
__except ( /* filter expression */ ) {
// termination code
}
// . . .
語法
try-except-statement:
__trycompound-statement__except (expression)compound-statement
備註
try-except語句是 C 和 C++ 語言的Microsoft延伸模組。 它可讓目標應用程式控制通常終止程序執行的事件。 這類事件稱為 結構化例外狀況,或簡短 的例外狀況 。 處理這些例外狀況的機制稱為 結構化例外狀況處理 (SEH)。
如需相關信息,請參閱 try-finally 語句。
例外狀況可能是硬體型或軟體型。 即使應用程式無法從硬體或軟體例外狀況完全復原,結構化例外狀況處理也很有用。 SEH 可讓您顯示錯誤資訊,並捕捉應用程式的內部狀態,以協助診斷問題。 對於不容易重現的間歇性問題特別有用。
備註
結構化例外狀況處理適用於 C 和 C++ 原始程式檔的 Win32。 不過,它並非專為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是 、 和 的__try__except__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> 中,且 _CONTEXT_EXCEPTION_RECORD 定義於 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