C++异常处理运行时是如何实现的?
-
20-08-2019 - |
题
我对 C++ 异常处理机制的工作原理很感兴趣。具体来说,异常对象存储在哪里以及它如何在多个范围中传播直到被捕获?它存储在某个全球区域吗?
由于这可能是特定于编译器的,有人可以在 g++ 编译器套件的上下文中解释一下吗?
解决方案
实现可能有所不同,但有一些根据需求得出的基本想法。
异常对象本身是在一个函数中创建、在其调用者中销毁的对象。因此,在堆栈上创建对象通常是不可行的。另一方面,许多异常对象并不是很大。因此,如果实际需要更大的异常对象,可以创建一个 32 字节的缓冲区并溢出到堆。
至于实际的控制权转移,存在两种策略。一种是在堆栈本身中记录足够的信息以展开堆栈。这基本上是要运行的析构函数和可能捕获异常的异常处理程序的列表。当异常发生时,返回执行这些析构函数的堆栈,直到找到匹配的 catch。
第二种策略将此信息移至堆栈外的表中。现在,当发生异常时,调用堆栈用于找出进入但未退出的范围。然后在静态表中查找这些异常,以确定将在何处处理抛出的异常,以及在其间运行哪些析构函数。这意味着堆栈上的异常开销更少;无论如何,都需要返回地址。这些表是额外的数据,但编译器可以将它们放入程序的按需加载段中。
其他提示
此在15.1定义投掷的标准的一个例外。
在掷创建临时对象。结果 如何对于此临时对象的存储器被分配是不确定的。
创建临时对象控制之后被传递到在所述调用栈中的最接近的处理程序。平仓抛出和捕获点之间的堆栈。作为堆栈放松任何堆栈变量被破坏在创建的顺序相反。
除非异常重新抛出临时在其中它被抓住的处理程序结束销毁。
注意:如果赶上通过参考引用将参考暂时的,如果通过临时对象被复制到值值赶上(并且因此需要一个拷贝构造)
。这S.Meyers通知(通过const引用捕捉)。
try
{
// do stuff
}
catch(MyException const& x)
{
}
catch(std::exception const& x)
{
}
这也可能有助于看看在普通的C用来实现的异常处理的一些基本类型的一招。这需要使用的setjmp()和longjmp()以下面的方式:前者保存在堆栈中为了标记异常处理程序(如“捕获”),而后者是用来“掷”的值。就好像它已经从一个调用的函数返回的“抛出”的值为止。的“试块”结束时的setjmp()被再次调用或当函数返回。
我知道这是一个老问题,但有一个很好的阐述,解释无论是在每个GCC和VC这里所采用的方法:的 http://www.hexblog.com/wp-content/uploads/2012/06/Recon-2012-Skochinsky-Compiler-Internals.pdf