19

如果我在非托管 C++、Visual Studio 2008 或更高版本中创建一个新项目,我想使用哪种异常处理模型?

我知道 /EHa 选项会导致代码效率降低,并且还会捕获 SEH 异常,对吗?

因此,我一直在避开该选项,并且通常使用 /EHsc,因此我只在 catch(...) 处理程序中捕获实际抛出的 C++ 异常,而不是捕获访问冲突和其他结构化异常。如果我的代码中存在访问冲突,我不希望它被 catch(...) {} 掩盖。

我与其他希望 catch(...) {} 什么都不做的人一起编写代码,如果存在访问冲突,他们甚至希望它这样做,这对我来说似乎是一个非常糟糕的主意。如果由于编码不好而出现错误,您不想将手指放在耳朵里大声说“啦啦啦啦啦!” 这样您就不必让程序崩溃?事实上,如果代码现在因为编码错误而处于不良状态,您真的希望代码继续吗?

所以我的一般想法是 /EHa 创建更大/更慢的代码,它允许程序员编写代码,如果存在致命错误,它将继续在未定义状态下运行。

顺便说一句,我说的是应用程序和服务代码,这是我们大部分时间编写的内容。不是低级设备驱动程序或类似的东西。

请权衡你的想法。

4

2 回答 2

22

/EHa 做了两件事。首先,如果代码分析器看不到任何可能引发 C++ 异常的代码,它会抑制忽略异常过滤器的优化,该过滤器会自动调用局部类变量的析构函数。这使得堆栈展开对于任何类型的异常都是安全的,而不仅仅是 C++ 异常。这些异常过滤器的开销是 x86 上的时间和 x86 和 x64 上的空间。

是的,它改变了 catch(...) 的行为,它现在还过滤任何 SEH 异常,而不仅仅是 C++。这确实是一场赌博,因为您捕获了所有真正令人讨厌的东西,即异步硬件异常。尽管我个人认为捕获所有 C++ 异常也不是很有防御性,但您仍然对程序状态发生变异的程度以及失败的原因有一个模糊的概念。

实际上,您需要切换到 using__try/__except以便您可以编写自己的异常过滤器并避免捕获不良过滤器。C++ 异常的异常代码是 0xe04d5343(“MSC”)。使用 _set_se_translator() 将是另一种方法。

于 2010-12-11T07:25:30.147 回答
6

我使用 /EHa 是因为 .NET interop 是安全的,而 /EHsc 可能不是;例如,请参阅当本机 (C++) 异常传播到 CLR 组件时未调用析构函数

但是,如果对于特定的代码位,额外的性能确实很重要,并且您不需要 .NET(或其他任何东西)兼容性,那么可以肯定,/EHsc 听起来不错。

/EHsc 和 /EHa 都不能捕获大多数内存错误,因此使用它们来捕获访问冲突是没有希望的情况。

于 2010-12-10T23:01:27.930 回答