零成本异常处理与setjmp / longjmp

时间:2011-02-12 00:44:06

标签: c++ exception gcc exception-handling g++

假设设置恢复点存在相关成本,可以像这样优化循环:

while (doContinue) {
   try {
     doSomeWork ();
   }
   catch (...) {}
}

这样的事情:

while (doContinue) {
   try {
      do {
        doSomeWork ();
      } while (doContinue);
      break;
   } catch (...) {}
}

但是如果平台支持零成本异常处理,那么这种优化没有任何意义。

有人能指出我是如何在不同的体系结构上实现零成本异常处理的,并且有一种方法可以确定编译器/代码生成器可用的底层机制,以便在编译时决定是否优化这样做。例如,编译器可以假设doSomeWork ()没有与循环相关的副作用吗?

2 个答案:

答案 0 :(得分:12)

只有在使用目标时才能使用零成本方法。如果可用,它将被大多数生产质量的C ++编译器使用。否则编译器将使用setjmp/longjmp方法。

setjmp/longjmp的执行速度较慢。

但是,即使使用setjmp/longjmp方法,使用异常机制也可以比检查每个函数的返回代码产生更高的性能,例如在问题中使用双循环优化。

找出目标是否支持零成本方法以及编译器是否正在使用的唯一方法是将C ++代码转换为汇编并进行分析。另一种解决方案是使用gnat调用--RTS=zcx并检查错误,如果gnat可用。但这并不能保证它将被C ++编译器使用。

因此,一般来说,如果程序大小不是问题并且零成本异常可用,则使用异常来处理意外情况要比检查每个函数的返回代码要好得多。否则,在某些情况下,可以使用异常来优化代码。

使用,但不要滥用!

P.S。:我最后在此写了article

答案 1 :(得分:7)

我认为你过高估计了“零成本”在这里意味着什么。这是LLVM doc就可以了;它的主要作用似乎是异常和上下文处理代码是在编译时构建的,因此在执行正常时,运行时没有额外的成本,成为一个时空权衡。在您的示例中,我相信会产生两倍的“着陆点”,增加大小并减慢异常处理。