/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” 的函式永遠不會throwC++例外狀況。 與 搭配 /EHa
使用時,它沒有任何作用(也就是說, /EHca
相當於 /EHa
)。 /EHc
如果未 /EHs
指定 或 /EHa
,則會忽略 。
r
告知編譯器針對所有 noexcept
函式一律產生執行階段終止檢查。 根據預設,如果編譯器判斷函式只會呼叫非擲回函式,則可能會繼續最佳化 noexcept
的執行階段檢查。 此選項會提供嚴格的C++一致性,但代價是一些額外的程序代碼。 /EHr
如果未 /EHs
指定 或 /EHa
,則會忽略 。
-
清除上一個選項自變數。 例如, /EHsc-
解譯為 /EHs /EHc-
,且 相當於 /EHs
。
/EH
自變數可以依任何順序個別指定或合併。 如果指定了相同自變數的多個實例,則最後一個實例會覆寫任何先前的實例。 例如, /EHr- /EHc /EHs
與 /EHscr-
相同,且 /EHscr- /EHr
效果與 /EHscr
相同。
備註
默認例外狀況處理行為
編譯程式一律會產生支援異步結構化例外狀況處理的程序代碼 (SEH)。 根據預設,編譯程序支援原生C++ catch(...)
子句中的處理程式,也就是未/EHsc
指定、 /EHs
或 /EHa
選項。SEH 不過,它也會產生僅部分支援C++例外狀況的程序代碼。 默認例外狀況回溯程序代碼不會終結因為例外狀況而超出範圍的區塊外部 try
的自動C++物件。 擲回C++例外狀況時,資源流失和未定義的行為可能會造成。
標準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
使用 來指定和嘗試處理所有例外catch(...)
狀況可能很危險。 在大部分情況下,非同步例外狀況無法復原,因此應視為嚴重。 攔截這些例外狀況並繼續執行可能造成處理序損毀,因而導致難以找出並修正的 Bug。
雖然 Windows 和 Visual C++ 支援 SEH,但我們強烈建議您使用 ISO 標準C++例外狀況處理 (/EHsc
或 /EHs
)。 這可讓您的程式碼更具可攜性和彈性。 有時候您可能必須在舊版程式代碼或特定種類的程式中使用 SEH 。 程序代碼中需要編譯以支援 Common Language Runtime (/clr
),例如。 如需詳細資訊,請參閱 結構化例外狀況處理。
我們建議您永遠不要將使用 編譯的物件檔案連結至使用 /EHa
/EHs
或 /EHsc
在同一個可執行檔模組中編譯的物件檔案。 如果您必須使用模組中的任何位置來處理異步例外 /EHa
狀況,請使用 /EHa
來編譯模組中的所有程序代碼。 您可以在與使用 /EHs
編譯的程式代碼相同的模組中使用結構化例外狀況處理語法。 不過,您無法將語法與 C++ try
、 throw
和 catch
混合SEH在相同的函式中。
如果您要catch由 以外的throw
項目所引發的例外狀況, 請使用 /EHa
。 這個範例將會產生並攔截結構化例外狀況:
// 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
屬性的函式。 根據預設,如果編譯程式後端判斷函式只呼叫 非擲 回函式,運行時間檢查可能會優化。 非擲回函式是具有指定不會擲回任何例外狀況之屬性的任何函式。 這些函式包含標示 noexcept
為 、 throw()
、 __declspec(nothrow)
和 的函式,指定時 /EHc
為 extern "C"
函式。 非擲回函式也包含編譯器判定檢查不會擲回任何例外狀況的任何函式。 您可以使用 明確設定預設行為 /EHr-
。
非擲回屬性不保證函式無法擲回例外狀況。 與函式的行為 noexcept
不同,MSVC 編譯程式會考慮使用 throw()
、 __declspec(nothrow)
或 extern "C"
宣告為未定義行為的函式所擲回的例外狀況。 使用這些三個宣告屬性的函式不會強制執行例外狀況的運行時間終止檢查。 您可以使用 /EHr
選項來協助您識別這個未定義的行為,方法是強制編譯程式針對逸 noexcept
出函式的未處理的例外狀況產生運行時間檢查。
在 Visual Studio 中設定選項,或以程式設計方式設定選項
在 Visual Studio 開發環境中設定這個編譯器選項
開啟專案的 [屬性頁] 對話方塊。 如需詳細資料,請參閱在 Visual Studio 中設定 C ++ 編譯器和組建屬性。
選取 [組態屬性>C/C++>Code 產生]。
修改 [啟用 C++ 例外狀況] 屬性。
或者,將 [啟用 C++ 例外狀況] 設定為 [否] ,然後在 [命令列] 屬性頁的 [其他選項] 方塊中,加入編譯器選項。
若要以程式方式設定這個編譯器選項
- 請參閱 ExceptionHandling。
另請參閱
MSVC 編譯程序選項
MSVC 編譯程式命令行語法
錯誤和例外狀況處理
例外狀況規格 (throw)
Structured Exception Handling (C/C++)