如何实现C ++exception处理运行时?
我对C ++exception处理机制如何工作很感兴趣。 具体来说,exception对象存储在哪里,它如何传播通过几个范围,直到被捕获? 它存储在一些全球性的地区吗?
由于这可能是编译器特定的,有人可以在g ++编译器套件的上下文中解释这一点吗?
实现可能有所不同,但是有一些基本的想法是从需求开始的。
exception对象本身是在一个函数中创build的对象,在其调用者中被销毁。 因此,在堆栈上创build对象通常是不可行的。 另一方面,很多exception对象并不是很大。 Ergo,如果实际需要更大的exception对象,可以创build例如32字节的缓冲区和堆溢出。
至于控制权的实际转移,存在两种策略。 一种是在堆栈中logging足够的信息来展开堆栈。 这基本上是一个运行析构函数和exception处理程序的列表,可能会发现exception。 发生exception时,运行这些析构函数的堆栈,直到find匹配的catch。
第二个策略是将这些信息转移到堆栈外的表中。 现在,当发生exception时,调用堆栈被用来找出哪个范围被input但是没有退出。 然后,在静态表中查找这些内容,以确定抛出exception将被处理的位置以及哪些析构函数在两者之间运行。 这意味着堆栈上的exception开销较less; 无论如何都需要返回地址。 这些表格是额外的数据,但编译器可以将它们放在程序的需求加载段中。
这是在15.1中定义的抛出标准的例外。
该throw创build一个临时对象。
未指定如何分配此临时对象的内存。
创build临时对象控件后,传递给调用堆栈中最接近的处理程序。 在抛出点和捕获点之间展开堆栈。 随着堆栈展开,任何堆栈variables都将按照创build的相反顺序销毁。
除非重新抛出exception,否则暂时在处理程序结束时被销毁。
注意:如果你通过引用来捕获引用将引用临时的,如果你通过值捕获临时对象被复制到值(因此需要一个复制构造函数)。
S.Meyers的build议(由const引用捕获)
try { // do stuff } catch(MyException const& x) { } catch(std::exception const& x) { }
你可以看看这里的详细解释。
这也可能有助于看看在纯C中使用的技巧来实现一些基本的exception处理。 这需要以下方式使用setjmp()和longjmp():前者保存堆栈以标记exception处理程序(如“catch”),而后者则用于“抛出”一个值。 “抛出的”值被看作是从被调用函数返回的。 “try块”在setjmp()被再次调用或函数返回时结束。
我知道这是一个古老的问题,但有一个非常好的说明,解释在这里每个gcc和VC使用的方法: http : //www.hexblog.com/wp-content/uploads/2012/06/Recon- 2012年Skochinsky编译器,Internals.pdf