共用方式為


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 可讓您顯示錯誤資訊,並捕捉應用程式的內部狀態,以協助診斷問題。 對於不容易重現的間歇性問題特別有用。

備註

結構化例外狀況處理適用於 C 和 C++ 原始程式檔的 Win32。 不過,它並非專為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是 、 和 的__try__except__leave同義字,除非指定編譯程式選項 /Za (停用語言延伸模組)。

__leave 關鍵詞

__leave關鍵詞只有在語句的try-except受防護區段中才有效,其效果是跳到受防護區段的結尾。 執行會在例外狀況處理程序之後的第一個語句繼續執行。

goto語句也可以跳出受防護的區段,而且不會降低效能,就像在 try-finally 語句中一樣。 這是因為不會發生堆疊回溯。 不過,我們建議您使用 __leave 關鍵詞,而不是 goto 語句。 原因是,如果受防護的區段很大或很複雜,您不太可能犯程序設計錯誤。

結構化例外狀況處理內部函數

結構化例外狀況處理提供兩個可用於 語句的內部 try-except 函數: GetExceptionCodeGetExceptionInformation

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

另請參閱

撰寫例外狀況處理程式
結構化例外狀況處理 (C/C++)
關鍵字