2010-09-24 82 views

回答

19

你实际上有三种机制:

  • C++异常,由编译器(try/catch
  • 结构化异常处理(SEH),Windows提供实现(__try/__except
  • MFC异常宏(TRY,CATCH - 建立在SEH/C++的异常之上 - 请参阅TheUndeadFish的评论)

C++异常通常保证在堆栈展开期间自动清理(即,本地对象的析构函数运行),其他机制不会。当他们被明确抛出

C++异常才会发生。结构化例外可能发生在许多操作中,例如由于未定义的行为,将无效指针传递给API,卸载内存映射文件的后备存储等等。

MFC做了介绍异常宏以支持例外即使编译器不执行。

+0

只是为了好奇,MFC曾经打算在VC++以外的任何编译器上工作? – 2010-09-24 13:49:51

+2

保证清理不需要C++异常。用/ EHa编译。 – 2010-09-24 14:27:05

+0

MFC确实在Watcom C/C++ 10上工作。不知何故。没有巫师和东西。 – peterchen 2010-09-24 14:28:59

6

A C++异常是编程语言C++的特征。 结构化异常是Windows操作系统的不同概念。 这两个使用类似的语法,但技术上不同。 Windows结构化异常不仅可用于C++,还可用于与C.

有时溶液统一两者的处理:在Windows应用程序可以提供一个处理函数,其捕捉所有结构化异常并抛出C++异常(由你定义)。

4

两者都提供错误发生时堆栈展开的机制。

结构化异常是由Windows提供,从内核的支持。如果您执行诸如访问无效内存位置之类的操作,它们会被Windows引发。它们也用于支持自动堆栈增长等功能。它们本身很少使用,但C++,.NET和类似语言中的语言异常通常建立在它们之上。您使用特殊关键字__try__catch来处理这些例外情况。但是,处理它们相对比较困难且容易出错,因为可以打破自动堆栈扩展等功能,并且可能会破坏C++语言异常。

C++异常由C++语言指定。被抛出和被捕获的数据类型是C++对象(包括原始类型的可能性)。编译器和运行时在底层结构化异常机制之上实现了这些功能。如果您使用C++语言的try,catchthrow关键字,就会得到这个结果。

SEH异常具有比C++异常更多的功能,例如支持恢复和所谓的“向量”处理程序(它接收异常通知但不一定防止堆栈解除),但除非您明确知道您想要使用它们,我会避免它们。如果您的程序执行某些非法或未定义的操作,可能最常用的方法是使用MiniDumpWriteDump编写故障转储。

1

C++异常将跨平台工作。不幸的是,SEH将严格限制可移植性(除了可能跨越不同的Windows版本)。

而且SEH似乎捕捉到大量的原生Windows异常(如访问冲突,被指定无效的句柄)等

7

这是一个沉重的实现细节,但在Windows C++异常也是一个SEH异常。异常代码是0xE04D5343(最后三个字节='MSC')。并且所有常规的SEH支持都用于展开堆栈,获取自动清理代码以运行并过滤异常,以便选择正确的catch子句。在过滤器表达式中获取抛出的异常对象是由CRT添加超出SEH提供的管道。 SEH也支持__finally子句,但在标准C++中没有使用。

另一个实现细节是/ EH编译器设置。缺省值(/ EHsc)允许编译器优化生成的代码并抑制运行自动清理所需的异常过滤器。如果它可以看到没有发出的C++代码可以抛出异常。这首先是一个空间优化,一个用于x86代码的小时间优化,但不适用于x64代码。为了自动清理SEH异常,必须使用/ EHa进行编译,以便优化被抑制。

与SEH结合使用C++异常的一个好方法是使用_set_se_translator(),因此您可以将SEH异常转换为C++异常。尽管追查SEH例外情况并不明智,但它们几乎总是令人讨厌。

+0

__try/__除块之外是否会捕获所有SEH异常以及所有C++异常? – Alexandru 2014-03-19 03:04:40

+0

另外需要注意的是,根据MSDN,对于具有try块的堆栈上的每个函数调用,仅调用_set_se_translator()一次,并且必须基于每个线程进行设置。 – Alexandru 2014-03-19 03:05:01