我对C++异常处理机制的工作方式感到好奇。具体来说,异常对象存储在哪里,以及它如何在多个作用域中传播直到被捕获?它是否存储在某个全局区域中?
由于这可能是与编译器有关的,因此能否有人在g ++编译器套件的上下文中解释这一点?
我对C++异常处理机制的工作方式感到好奇。具体来说,异常对象存储在哪里,以及它如何在多个作用域中传播直到被捕获?它是否存储在某个全局区域中?
由于这可能是与编译器有关的,因此能否有人在g ++编译器套件的上下文中解释这一点?
实现可能会有所不同,但是一些基本的想法是从需求中得出的。
异常对象本身是在一个函数中创建的对象,在调用者中被销毁。因此,通常无法在堆栈上创建对象。另一方面,许多异常对象并不是很大。因此,可以创建一个32字节的缓冲区,并在需要更大的异常对象时溢出到堆。
关于实际的控制转移,存在两种策略。其中一种是在堆栈本身中记录足够的信息以展开堆栈。这基本上是一个要运行的析构函数列表和可能捕获异常的异常处理程序。当发生异常时,回溯堆栈执行那些析构函数,直到找到匹配的catch。
第二种策略将此信息移动到堆栈外的表中。现在,当发生异常时,调用堆栈用于查找已进入但未退出的范围。然后,在静态表中查找这些范围,以确定将处理抛出的异常的位置以及在其中运行哪些析构函数。这意味着堆栈上的异常开销较少;返回地址仍然需要。表是额外的数据,但编译器可以将它们放在程序的需求加载段中。
free()
或fclose()
。 - MSalters这个定义在标准的 15.1 抛出异常中。
throw语句创建了一个临时对象,但是如何分配该临时对象的内存是未指定的。
在创建临时对象后,控制权将传递给调用堆栈中最近的处理程序,从 throw 到 catch 点之间解开堆栈。由于堆栈被解开,任何堆栈变量都会按照创建顺序相反的顺序被销毁。
除非异常被重新抛出,否则临时对象将在它被捕获的处理程序结束时被销毁。
注意:如果你使用引用方式捕获异常,那么该引用将会引用到临时对象上,如果你使用值方式捕获异常,该临时对象会被复制到值上(因此需要一个复制构造函数)。
建议来自 S.Meyers(采用 const 引用方式捕获异常)。
try
{
// do stuff
}
catch(MyException const& x)
{
}
catch(std::exception const& x)
{
}
我知道这是一个老问题,但这里有一个非常好的解释,解释了gcc和VC中使用的各种方法:http://www.hexblog.com/wp-content/uploads/2012/06/Recon-2012-Skochinsky-Compiler-Internals.pdf