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 子句後面的複合陳述式則是例外狀況處理常式。 處理常式會指定在主體區段執行期間引發例外狀況時要採取的動作。 執行程序如下所示:

  1. 執行保護的區段。

  2. 如果執行保護的區段時未發生例外狀況,則會在 __except 子句之後的陳述式繼續執行。

  3. 如果在受防護區段執行期間發生例外狀況,或在受防護區段呼叫的任何常式中,則會 __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

另請參閱

撰寫例外狀況處理常式
Structured Exception Handling (C/C++)
關鍵字