/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++ try
、 throw
和 catch
混合 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)
和 的函式,指定時 /EHc
為 extern "C"
函式。 throw非 ing 函式也包含編譯器已判斷的任何函式,都是透過檢查進行非 throw 檢查。 您可以使用 明確設定預設行為 /EHr-
。
非 throw ing 屬性不保證函式無法將例外狀況設定為 throw n。 不同于函式的行為 noexcept
,MSVC 編譯器會 throw 考慮使用 throw()
、 __declspec(nothrow)
或 extern "C"
宣告為未定義行為的函式 n 例外狀況。 使用這些三個宣告屬性的函式不會強制執行例外狀況的執行時間終止檢查。 您可以使用 /EHr
選項來協助您識別這個未定義的行為,方法是強制編譯器針對逸 noexcept
出函式的未處理的例外狀況產生執行時間檢查。
在 Visual Studio 中設定選項,或以程式設計方式設定選項
在 Visual Studio 開發環境中設定這個編譯器選項
開啟專案的 [屬性頁] 對話方塊。 如需詳細資料,請參閱在 Visual Studio 中設定 C ++ 編譯器和組建屬性。
選取 [ 組態屬性 > C/C++ > 程式碼產生]。
修改 [啟用 C++ 例外狀況] 屬性。
或者,將 [啟用 C++ 例外狀況] 設定為 [否] ,然後在 [命令列] 屬性頁的 [其他選項] 方塊中,加入編譯器選項。
若要以程式方式設定這個編譯器選項
- 請參閱 ExceptionHandling。
另請參閱
MSVC 編譯器選項
MSVC 編譯器命令列語法
錯誤和例外狀況處理
例外狀況規格 ( throw )
Structured Exception Handling (C/C++)
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應