【发布时间】:2011-04-13 10:32:23
【问题描述】:
我想知道捕获我抛出的异常的更好方法是:它是 __try / __except 块还是 try / catch 块?
我是用 C++ 编写的,该程序只能在 Windows 上使用,所以可移植性不是问题。
谢谢!
【问题讨论】:
标签: c++ c performance exception try-catch
我想知道捕获我抛出的异常的更好方法是:它是 __try / __except 块还是 try / catch 块?
我是用 C++ 编写的,该程序只能在 Windows 上使用,所以可移植性不是问题。
谢谢!
【问题讨论】:
标签: c++ c performance exception try-catch
它们是两个非常不同的东西。 try/catch 是您熟悉的 C++ 关键字。 __try/__except 用于捕获 SEH 异常。 Windows 本身引发的异常,例如 DivisionByZero 或 AccessViolation。在MSDN Library article 中对此进行了很好的描述。
您还可以使用它来捕获 C++ 异常,因为它利用了 Windows SEH 功能。但是,您无法从中获取抛出的异常对象,因此如果您确实想要处理异常,则上下文为零。这是疯狂。第一种方法是永远不要捕获 SEH 异常,它们总是很严重。如果您确实需要将两者结合起来,请使用 _set_se_translator() 将 SEH 异常转换为 C++ 异常。
【讨论】:
__try/__except 设计用于调用不支持异常但使用结构化错误代码/处理机制的 Win32 C 代码。 __try/__except 会将 C 错误转换为与 C++ try/catch 相似 的异常块。
有关详细信息,请参阅this MSDN article。
【讨论】:
标准 C++ 使用 try/catch 块,所以如果您需要基于标准 C++ 库的“标准”异常机制,我建议使用它们。
但是,如果您计划使用通过 Windows SDK 提供的结构化异常处理(请参阅here),请使用__try/__except。
【讨论】:
std::exception 不是 STL 类。
您应该使用try/catch 块。
正如其他人已经回答的那样,__try / __except 用于捕获 SEH(Windows 生成的错误),而不是用于捕获一般异常。
最重要的是,__try 和 __catch 在抛出异常时可能无法运行 C++ 析构函数或正确展开堆栈。
除非在极少数情况下,否则永远不要尝试捕获 SEH 异常。
编辑:好吧,我对此持肯定态度(这是我一直被告知的),但@Hans 说显然有一个编译器开关可以用来改变它。我认为/EHa 上的文档对这里发生的事情具有误导性,或者至少是不完整的。如果有人找到证明此错误的权威文档,我会很乐意删除此答案。
即使事实证明这是错误的,您仍然应该使用 try 和 catch,因为它们是标准的,而 __try 和 __except 不是。
【讨论】:
__try 和 __except 严格来说是基于 C 的 API/ABI。
/EHa 的理解仅仅是它允许C++ 异常处理构造(当您使用try 和catch 时)捕获SEH 异常,但是当__try 和__except 时C++ 堆栈仍然没有正确展开被使用。
__except 可以捕获 C++ 异常;但我的理解是,这样做时不能保证提供 C++ 堆栈展开语义。除非,正如 Hans 所说,在/EHa 下。 (请不要使用/EHa)
一旦你扔了东西,你就再也没有太多选择来抓住它了。如果您抛出 C++ 异常(即使用throw),则使用try/catch。如果您抛出 Windows 异常(即使用RaiseException),则使用__try/__except。试图混合它们只会给你的生活增加不必要的麻烦。
【讨论】:
RaiseException扔它,所以你必须用__except抓住它。