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(同步与异步异常处理)的主要内容,如果未能解决你的问题,请参考以下文章