【发布时间】:2011-04-16 17:51:48
【问题描述】:
有人可以解释 C++ 异常和 MFC 中结构化异常之间的区别吗?
【问题讨论】:
有人可以解释 C++ 异常和 MFC 中结构化异常之间的区别吗?
【问题讨论】:
这是一个繁重的 MSVC++ 实现细节,但在 Windows 上,C++ 异常也是 SEH 异常。异常代码为 0xE04D5343(最后三个字节 = 'MSC')。并且所有常规 SEH 支持都用于展开堆栈、运行自动清理代码并过滤异常以便选择正确的 catch 子句。作为demonstrated here。
在过滤器表达式中获取抛出的异常对象是 CRT 添加的管道,超出了 SEH 提供的范围,因为它是特定于 C++ 的,所以必然如此。
另一个实现细节是 /EH 编译器设置。默认值 (/EHsc) 允许编译器优化生成的代码并抑制运行自动清理所需的异常过滤器。如果它可以看到所有发出的 C++ 代码都不会引发异常。要自动清除 SEH 异常,您必须使用 /EHa 进行编译,以便抑制这种优化。
将 C++ 异常与 SEH 结合的一种策略是使用 _set_se_translator(),以便您可以将 SEH 异常转换为 C++ 异常。尽管捕获 SEH 异常通常并不明智,但它们几乎总是令人讨厌的。您通常倾向于使用 __try/__catch,如链接答案所示。
【讨论】:
你实际上有三种机制:
try/catch)__try / __except) 提供TRY、CATCH - 建立在 SEH / C++ 异常之上 - 另见 TheUndeadFish 的评论)C++ 异常通常保证在堆栈展开期间自动清理(即运行本地对象的析构函数),而其他机制则不能。
C++ 异常仅在显式抛出时发生。许多操作可能会出现结构化异常,例如由于未定义的行为、向 API 传递无效指针、卸载内存映射文件的后备存储等等。
MFC 确实引入了异常宏来支持异常,即使编译器没有实现它们。
【讨论】:
C++ 异常可以跨平台工作。不幸的是,SEH 将严重限制可移植性(可能跨不同的 Windows 版本除外)。
SEH 似乎还捕获了许多本机 Windows 异常(如访问冲突、指定了无效句柄)等。
【讨论】:
两者都提供了发生错误时堆栈展开的机制。
结构化异常由 Windows 提供,并得到内核的支持。如果您执行诸如访问无效内存位置之类的操作,它们会由 Windows 引发。它们还用于支持自动堆栈增长等功能。它们很少单独使用,但 C++、.NET 和类似语言中的语言异常通常是在它们之上构建的。您可以使用 __try 和 __catch 等特殊关键字来处理这些异常。但是,处理它们相对困难且容易出错,因为您可能会破坏自动堆栈扩展等功能,以及可能破坏 C++ 语言异常。
C++ 异常由 C++ 语言指定。抛出和捕获的数据类型是 C++ 对象(包括原始类型的可能性)。编译器和运行时在底层结构化异常机制之上实现这些。如果您使用 C++ 语言的 try、catch 和 throw 关键字,这就是您所得到的。
SEH 异常比 C++ 异常具有更多功能,例如支持恢复,以及所谓的“矢量化”处理程序(接收异常通知,但不一定阻止堆栈展开),但除非您明确知道要使用他们,我会避开他们。如果您的程序做了非法或未定义的事情,它们最常见的用途可能是使用MiniDumpWriteDump 编写故障转储。
【讨论】:
C++ 异常是编程语言 C++ 的一个特性。 结构化异常是 Windows 操作系统的不同概念。 这两个使用相似的语法,但在技术上是不同的。 Windows 结构化异常不仅可用于 C++,还可用于例如与 C.
有时是统一处理两者的解决方案:在 Windows 应用程序中,您可以提供一个处理函数,该函数捕获所有结构化异常并引发 C++ 异常(由您定义)。
【讨论】: