/EH(异常处理模型)

指定编译器要使用的异常处理种类,并且销毁由于异常的原因导致超出范围的 C++ 对象。 如果未指定 /EH,则编译器将同时捕获异步结构化异常和 C++ 异常,但不会销毁由于异步异常超出范围的 C++ 对象。

/EH{s|a}[c][-]

参数

  • a
    同时捕获异步(结构化)和同步 (C++) 异常的异常处理模型。

  • s
    仅捕获 C++ 异常并通知编译器假定声明为 extern "C" 的函数可能引发异常的异常处理模型。

  • c
    如果与 s (/EHsc) 一起使用,则仅捕获 C++ 异常并通知编译器假定声明为 extern "C" 的函数从未引发 C++ 异常。

    /EHca/EHa 相等。

备注

/EHa 编译器选项用于支持使用本机 C++ catch(...) 子句的异步结构化异常处理 (SEH)。 若要在不指定 /EHa 的情况下实现 SEH,则可以使用 __try, __except 和 __finally 语法。 尽管 Windows 和 Visual C++ 支持 SEH,但强烈建议你使用 ISO 标准 C++ 异常处理(/EHs/EHsc),因为它使代码更可移植并更灵活。 但是,在现有代码中或对于特定程序类型(例如,在编译为支持公共语言运行时 (/clr(公共语言运行时编译)) 的代码中),你仍可能必须使用 SEH。 有关详细信息,请参阅结构化异常处理 (C/C++)

指定 /EHa 并尝试使用 catch(...) 处理所有异常可能很危险。 在大多数情况下,异步异常是不可恢复的,因而被认为是致命的。 捕获它们并继续可能导致进程损坏并使 Bug 难以发现和修复。

如果使用 /EHs/EHsc,则 catch(...) 子句不会捕捉异步结构化异常。 将捕获不到访问冲突和托管 Exception 异常,并且范围内的对象产生了异步异常也不会被销毁(即使异步异常已处理)。

如果使用 /EHa,则映像可能更大,并且可能也无法执行,因为编译器没有显著优化 try,并且它留在自动调用所有本地对象的析构函数的异常筛选器中(即使编译器未看到可引发 C++ 异常的任何代码)。 这使你可以为异步异常和 C++ 异常展开安全堆栈。 当你使用 /EHs时,编译器假定异常只在 throw 语句或函数调用处发生。 这使编译器能够消除代码以跟踪很多不可展开对象的生存期,并且这也能显著减小代码大小。

建议你不要在同一可执行模块中将使用 /EHa 编译的对象与使用 /EHs 编译的对象链接在一起。 如果必须通过在模块中的任意位置使用 /EHa 来处理异步异常,则在此模块中使用 /EHa 来编译所有代码。 可在与使用 /EHs 编译的代码相同的模块中使用结构化异常处理语法,但不能将 SEH 语法与同一函数中的 try、throw 和 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;
   }
}

/EHc 选项需要指定 /EHs/EHa。 使用 /clr 将隐式使用 /EHa(即**/clr /EHa** 是冗余的)。 如果在 /clr 后使用 /EHs[c],编译器将产生一个错误。 优化不会影响此行为。 当捕获到某个异常时,编译器将为与该异常在同一范围内的对象调用类析构函数。 如果未捕获到异常,则不会运行这些析构函数。

有关 /clr 下的异常处理限制的信息,请参见 _set_se_translator

可以使用符号 - 清除该选项。 例如,/EHsc- 解释为 /EHs /EHc- 并且等效于 /EHs

在 Visual Studio 开发环境中设置此编译器选项

  1. 打开项目的**“属性页”**对话框。 有关详细信息,请参见如何:打开项目属性页

  2. 在左窗格中,展开**“配置属性”“C/C++”“代码生成”**。

  3. 修改**“启用 C++ 异常”**属性。

    或者,将**“启用 C++ 异常”设置为“No”,然后在“命令行”属性页中的“附加选项”**框中键入编译选项。

以编程方式设置此编译器选项

请参见

参考

编译器选项

设置编译器选项

异常规范

结构化异常处理 (C/C++)

概念

错误和异常处理(现代 C++)