共用方式為


結構化例外狀況處理 (C/C++)

結構化例外狀況處理 (SEH) 是 C 的Microsoft延伸模組,C++來處理某些例外程式代碼狀況,例如硬體錯誤,正常運作。 雖然 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 機制:

這兩種處理程式是不同的,但透過稱為 回溯堆疊的程式密切相關。 發生結構化例外狀況時,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 來編譯此程序代碼,但未定義本機測試控件巨集 CPPEXTestClass 解構函式不會執行。 輸出如下所示:

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 特定

另請參閱

例外狀況處理
關鍵字
<exception>
錯誤和例外狀況處理
結構化例外狀況處理 (Windows)