MSVC - /EHsc 与 /EHa(同步与异步异常处理)

Posted

技术标签:

【中文标题】MSVC - /EHsc 与 /EHa(同步与异步异常处理)【英文标题】:MSVC - /EHsc vs /EHa (synchronous vs asynchronous exception handling) 【发布时间】:2011-01-01 08:15:57 【问题描述】:

您能否列出实际差异/含义的项目符号列表?我阅读了相关的 MSDN 文章,但我对异步异常的理解仍然有点模糊。

我正在使用 Boost.Test 编写一个测试套件,我的编译器发出一条警告说应该启用 EHa:

警告 C4535:调用 _set_se_translator() 需要 /EHa

项目本身仅使用普通异常(来自 STL)并且不需要 /EHa 开关。我是否必须使用 /EHa 开关重新编译它才能使测试套件正常工作?我的感觉是我只需要 /EHa 作为测试服。

【问题讨论】:

【参考方案1】:

当您使用 /EHsc 时,当编译器检测到包装在 try 块中的代码可能引发 C++ 异常时,它只会发出用于异常过滤器的代码。异常过滤器确保在处理异常时展开堆栈时调用任何本地 C++ 对象的析构函数。它使 RAII 工作。

这是一个优化,x86 代码的空间和时间,x64 代码的空间。空格,因为它可以省略异常过滤器代码,顺便说一句,这是适度的。时间,因为在 x86 上它可以避免在进入 try 块时注册异常过滤器。顺便说一句,非常谦虚。 x64 使用不同的方式来查找异常过滤器,它是基于表的。

第一段的关键词是“可能抛出 C++ 异常”。在 Windows 上还有其他异常来源。与 /EHa 中的“a”一样,硬件引发的异步异常。诸如浮点异常、被零除和万能的访问冲突异常之类的事情。但也值得注意的是您可能与之交互的代码引发的异常类型。就像托管代码一样,基本上是在 VM 中运行的任何东西。

如果你想让你的对象对这些类型的异常也安全,那么你需要使用 /EHa,它告诉编译器总是注册异常过滤器。

当心 /EHa 的一个讨厌的副作用,它使 catch(...) 吞下 所有 异常。包括那些你不应该抓住的,比如 AV 和 SO。如果这对您很重要,请查看 __try/__except 和 _set_se_translator()。

【讨论】:

【参考方案2】:

好吧,如果没有 /EHa,您将无法捕获意外异常,因此您的测试程序将异常退出。

如果能做异常退出的测试,最好不要和/EHa搏斗。

此外,将选项更改为 /EHa 会产生许多副作用,包括增加可执行文件大小和几乎没有性能下降。如此有效地改变了原来的行为。

使用或不使用 /EHa 是通常在程序设计阶段做出的重大决定。

恕我直言,测试用例编写中的问题对于改变这个决定来说是微不足道的。

【讨论】:

以上是关于MSVC - /EHsc 与 /EHa(同步与异步异常处理)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Visual Studio 2003 上指定 /EHa

如何关闭Microsoft编译器(cl)中的异常?

同步/异步和阻塞/非阻塞

同步与异步阻塞与非阻塞

Java 同步与异步-阻塞与非阻塞理解

武田在ASCO和EHA上展示肿瘤学产品组合和研发产品线的最新研究成果