Visual C ++具有编译器设置“启用C ++异常”,可以将其设置为“否”。如果我这样设置会发生什么?我的代码从不显式抛出或捕获异常(因此第一个抛出的异常将终止程序)并且不依赖于堆栈展开 - 我是否应该从重新编译的程序中得到更多不受欢迎的行为?
答案 0 :(得分:15)
MSDN documentation of the setting解释了不同的异常模式,甚至提供了代码示例来显示不同模式之间的差异。此外,this article可能很有趣,即使它已经很老了。
底线:该选项基本上启用或禁用跟踪所有对象的生命周期。这种跟踪是必需的,因为在异常的情况下,需要调用所有正确的析构函数,必须展开堆栈,并进行大量的清理工作。这种跟踪需要组织开销(=附加代码) - 可以通过将选项设置为“否”来删除。
我自己没试过,但如果选项设置为“No”,看起来你仍然可以throw
和catch
例外,但是缺少清理和展开,可能会产生非常糟糕的后果(不推荐;)..
答案 1 :(得分:4)
编译器将省略析构函数和其他堆栈展开代码,这些代码在C ++对象作为异常结果超出范围时清理。
换句话说,它遗漏了一堆清理代码。这will significantly improve performance,但如果异常实际上被抛出,也会造成严重的罪恶。 (如果你不相信我,请自己计时。)
性能差异并不是禁用异常的真正原因,除非在您必须这样做的某些关键应用程序中。
答案 2 :(得分:2)
如果对“启用C ++异常”说“否”,则不会选择编译器的异常处理同步模型(/ GX或/ EHsc)。在此模式下,将不启用展开语义。也就是说,在执行throw的函数和捕获函数的函数之间的框架中具有自动存储的对象将不会被破坏。
您可以参考MSDN或A Visual C++ Exception FAQ了解有关异常处理的更多详细信息。
class Test
{
public:
Test()
{
printf("Test::constructor");
}
~Test()
{
printf("Test::Destructor");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
int a;
try
{
Test a;
int* p = 0;
*p = 0; // Cause access violation
}
catch (...)
{
printf("Caught access violation");
}
return 0;
}
如果没有异常处理输出将是:
Test::constructor
Caught access violation
答案 3 :(得分:2)
您仍然可以访问结构化异常处理(SEH),它可以由__try,__ except和__finally处理。
C ++异常处理只是建立在SEH之上的类实现。
如果您尝试在具有SEH异常处理程序的函数中实例化类(抱怨需要展开的对象,即类),编译器也会抱怨,这可能有点乱,但有办法解决它。
答案 4 :(得分:2)
我使用的代码总是关闭异常。我没有看到腐败或资源匮乏的问题。
我认为异常通常与c ++不合适。堆栈爆破,特别是缺少GC使得整个例外情况变得很痛苦。然后关于什么“特殊”真正意味着与失败的可能性相比的辩论。
答案 5 :(得分:1)
就标准C ++而言,您将获得未定义的行为。 C ++标准不承认全局关闭异常的可能性,某些标准库操作被定义为在某些情况下抛出异常。
答案 6 :(得分:0)
如果operator new
无法分配内存,我相信它会返回NULL
而不是抛出std::bad_alloc
例外。
如果您对抛出异常的第三方库进行任何调用,则会导致很多不良。