/EH (例外狀況處理模型)

指定編譯器所產生的例外狀況處理模型支援。 引數會指定是否將語法同時套用 catch(...) 至結構化和標準 C++ 例外狀況、是否 extern 將 「C」 程式碼假設為 throw 例外狀況,以及是否要優化特定 noexcept 檢查。

語法

/EHa[-]
/EHs[-]
/EHc[-]
/EHr[-]

引數

a
啟用標準 C++ 堆疊回溯。 當您使用 catch(...) 語法時,會攔截結構化 (非同步) 和標準 C++ (同步) 例外狀況。 /EHa 會覆 /EHs 寫 和 /EHc 引數。

s
啟用標準 C++ 堆疊回溯。 當您使用 catch(...) 語法時,只攔截標準 C++ 例外狀況。 除非 /EHc 也指定 ,否則編譯器會假設宣告為 extern 「C」 的 函式可能會 throw 是 C++ 例外狀況。

c
搭配 /EHs 使用 時,編譯器會假設宣告為 extern 「C」 的 函式絕對不會 throw 是 C++ 例外狀況。 與 搭配 /EHa 使用時,它沒有任何作用(也就是說, /EHca 相當於 /EHa )。 /EHc 如果未 /EHs 指定 或 /EHa ,則會忽略 。

r
告知編譯器針對所有 noexcept 函式一律產生執行階段終止檢查。 根據預設,如果編譯器只呼叫非 throw ing 函式,執行時間檢查 noexcept 可能會優化。 此選項會提供嚴格的 C++ 一致性,但代價是一些額外的程式碼。 /EHr 如果未 /EHs 指定 或 /EHa ,則會忽略 。

-
清除上一個選項引數。 例如, /EHsc- 解譯為 /EHs /EHc- ,且 相當於 /EHs

/EH 引數可以依任何順序個別指定或合併。 如果指定了相同引數的多個實例,則最後一個實例會覆寫任何先前的實例。 例如, /EHr- /EHc /EHs/EHscr- 相同,且 /EHscr- /EHr 效果與 /EHscr 相同。

備註

預設例外狀況處理行為

編譯器一律會產生支援非同步結構化例外狀況處理的程式碼 ( SEH )。 根據預設,編譯器支援 SEH 原生 C++ catch(...) 子句中的處理常式(也就是未 /EHsc 指定 、 /EHs/EHa 選項)。 不過,它也會產生僅部分支援 C++ 例外狀況的程式碼。 預設例外狀況回溯程式碼不會終結因為例外狀況而超出範圍的區塊外 try 自動 C++ 物件。 當 C++ 例外狀況為 throw n 時,資源流失和未定義的行為可能會造成。

標準 C++ 例外狀況處理

標準 C++ 例外狀況處理模型的完整編譯器支援,可安全地回溯堆疊物件 /EHsc (建議)、 /EHs/EHa

如果您使用 /EHs/EHsc ,則子 catch(...) 句不會 catch 非同步結構化例外狀況。 任何存取違規和受控 System.Exception 例外狀況都無法攔截。 此外,即使程式碼處理非同步例外狀況,也不會終結非同步例外狀況時範圍中的物件。 此行為是讓結構化例外狀況無法處理的引數。 相反地,請考慮這些例外狀況是致命的。

當您使用 /EHs/EHsc 時,編譯器會假設例外狀況只能在 throw 語句或函式呼叫發生。 此假設可讓編譯器排除程式碼來追蹤許多可回溯物件的存留期,這可大幅減少程式碼大小。 如果您使用 /EHa ,則可執行檔映射可能較大且較慢,因為編譯器不會積極優化 try 區塊。 它也會保留在例外狀況篩選中,以自動清除本機物件,即使編譯器看不到任何可 throw 發生 C++ 例外狀況的程式碼也一樣。

結構化和標準 C++ 例外狀況處理

編譯器 /EHa 選項可啟用非同步例外狀況和 C++ 例外狀況的安全堆疊回溯。 它支援使用原生 C++ catch(...) 子句處理標準 C++ 和結構化例外狀況。 若要實 SEH 作 /EHa 而不指定 ,您可以使用 __try__except__finally 語法。 如需詳細資訊,請參閱 結構化例外狀況處理

重要

使用 /EHa 來指定和 try 處理所有例外狀況 catch(...) 可能很危險。 在大部分情況下,非同步例外狀況無法復原,因此應視為嚴重。 攔截這些例外狀況並繼續執行可能造成處理序損毀,因而導致難以找出並修正的 Bug。

雖然 Windows 和 Visual C++ 支援 SEH ,但我們強烈建議您使用 ISO 標準 C++ 例外狀況處理 ( /EHsc/EHs )。 它可讓您的程式碼更具可攜性和彈性。 有時候您可能必須在舊版程式碼或特定種類的程式中使用 SEH 。 程式碼中需要編譯以支援 Common Language Runtime ( /clr ),例如。 如需詳細資訊,請參閱 結構化例外狀況處理

我們建議您永遠不要將使用 編譯的物件檔案連結至使用 /EHa/EHs/EHsc 在同一個可執行檔模組中編譯的物件檔案。 如果您必須使用模組中的任何位置來處理非同步例外 /EHa 狀況,請使用 /EHa 來編譯模組中的所有程式碼。 您可以在與使用 /EHs 編譯的程式碼相同的模組中使用結構化例外狀況處理語法。 不過,您無法將語法與 C++ trythrowcatch 混合 SEH 在相同的函式中。

如果您想要 catch 由 以外的 throw 專案所引發的例外狀況,請使用 /EHa 。 此範例會產生並 catch 產生結構化例外狀況:

// compiler_options_EHA.cpp
// compile with: /EHa
#include <iostream>
#include <excpt.h>
using namespace std;

void fail()
{
    // generates SE and attempts to catch it using catch(...)
    try
    {
        int i = 0, j = 1;
        j /= i;   // This will throw a SE (divide by zero).
        printf("%d", j);
    }
    catch(...)
    {
        // catch block will only be executed under /EHa
        cout << "Caught an exception in catch(...)." << endl;
    }
}

int main()
{
    __try
    {
        fail();
    }

    // __except will only catch an exception here
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        // if the exception was not caught by the catch(...) inside fail()
        cout << "An exception was caught in __except." << endl;
    }
}

/clr 下的例外狀況處理

選項 /clr 表示 /EHa (也就是 /clr /EHa ,是多餘的)。 如果 /EHs 或 是在 之後 /clr 使用 或 /EHsc ,編譯器會產生錯誤。 優化不會影響此行為。 攔截到例外狀況時,編譯器會針對與例外狀況位於相同範圍中的任何物件叫用類別解構函式。 如果未攔截到例外狀況,則不會執行這些解構函式。

如需 底下 /clr 例外狀況處理限制的資訊,請參閱 _set_se_translator

執行時間例外狀況檢查

選項 /EHr 會強制執行時間終止檢查所有具有 noexcept 屬性的函式。 根據預設,如果編譯器後端判斷函式只呼叫 非 throw ing 函式,執行時間檢查可能會優化。 throw非 ing 函式是任何具有屬性且沒有指定例外狀況的函式可能是 throw n。 這些函式包含標示 noexcept 為 、 throw()__declspec(nothrow) 和 的函式,指定時 /EHcextern "C" 函式。 throw非 ing 函式也包含編譯器已判斷的任何函式,都是透過檢查進行非 throw 檢查。 您可以使用 明確設定預設行為 /EHr-

非 throw ing 屬性不保證函式無法將例外狀況設定為 throw n。 不同于函式的行為 noexcept ,MSVC 編譯器會 throw 考慮使用 throw()__declspec(nothrow)extern "C" 宣告為未定義行為的函式 n 例外狀況。 使用這些三個宣告屬性的函式不會強制執行例外狀況的執行時間終止檢查。 您可以使用 /EHr 選項來協助您識別這個未定義的行為,方法是強制編譯器針對逸 noexcept 出函式的未處理的例外狀況產生執行時間檢查。

在 Visual Studio 中設定選項,或以程式設計方式設定選項

在 Visual Studio 開發環境中設定這個編譯器選項

  1. 開啟專案的 [屬性頁] 對話方塊。 如需詳細資料,請參閱在 Visual Studio 中設定 C ++ 編譯器和組建屬性

  2. 選取 [ 組態屬性 > C/C++ > 程式碼產生]。

  3. 修改 [啟用 C++ 例外狀況] 屬性。

    或者,將 [啟用 C++ 例外狀況] 設定為 [否] ,然後在 [命令列] 屬性頁的 [其他選項] 方塊中,加入編譯器選項。

若要以程式方式設定這個編譯器選項

另請參閱

MSVC 編譯器選項
MSVC 編譯器命令列語法
錯誤和例外狀況處理
例外狀況規格 ( throw )
Structured Exception Handling (C/C++)