Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 零成本异常处理与setjmp/longjmp_C++_Exception_Gcc_Exception Handling_G++ - Fatal编程技术网

C++ 零成本异常处理与setjmp/longjmp

C++ 零成本异常处理与setjmp/longjmp,c++,exception,gcc,exception-handling,g++,C++,Exception,Gcc,Exception Handling,G++,假设与设置恢复点相关的成本,可以优化如下循环: while (doContinue) { try { doSomeWork (); } catch (...) {} } while (doContinue) { try { do { doSomeWork (); } while (doContinue); break; } catch (...) {} } 变成这样: while (doContinu

假设与设置恢复点相关的成本,可以优化如下循环:

while (doContinue) {
   try {
     doSomeWork ();
   }
   catch (...) {}
}
while (doContinue) {
   try {
      do {
        doSomeWork ();
      } while (doContinue);
      break;
   } catch (...) {}
}
变成这样:

while (doContinue) {
   try {
     doSomeWork ();
   }
   catch (...) {}
}
while (doContinue) {
   try {
      do {
        doSomeWork ();
      } while (doContinue);
      break;
   } catch (...) {}
}
但若平台支持零成本异常处理,那个么这种优化就并没有任何意义


有人能告诉我零成本异常处理是如何在不同的体系结构上实现的吗?有没有一种方法可以说明编译器/代码生成器可以使用哪些底层机制在编译时决定是否这样优化。例如,如果编译器可以假设
doSomeWork()
没有与循环相关的副作用,它是否可以为您优化它?

我认为您高估了“零成本”的含义。这是上面的说明;它的主要作用似乎是,异常和上下文处理代码是在编译时生成的,因此在执行正常进行时,在运行时没有额外的成本,这成为一种时空权衡。在您的示例中,我相信生成的“着陆垫”数量将是原来的两倍,从而增加了尺寸并减缓了异常处理。

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

setjmp/longjmp
的执行速度较慢

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

<> P>是将C++代码转换为汇编并分析它的唯一方法。另一种解决方案是使用
--RTS=zcx
调用
gnat
,如果
gnat
可用,则检查错误。但是这不能保证它将被C++编译器使用。 所以一般来说,如果程序大小不是一个问题,并且可以使用零成本异常,那么使用异常来处理意外情况比检查每个函数的返回代码要好得多。否则,在某些情况下,可以使用异常来优化代码

使用,但不要滥用


附言:我最后写了一篇关于这个的文章。

零成本异常处理是否可行?我不知道,但对我来说它似乎没有完全优化编译。你可以用它来检查两种解决方案的“合理”组合。@9dan:是的,这是完全可能的。我在我的例子中在英特尔内核2中的C++代码片段中生成了汇编,在Mac OS X上用GCC 4.6进行了。在这个程序中,你可以看到没有任何开销与<代码>尝试catch < /Cord>块。抛出/捕获时总是有开销,但如果没有出现这些异常情况,则运行时的成本为零。在使用额外指令Vlad时看不到这一点,但在禁用使用C编译时可能发生的某些优化时可以看到这一点。开销很小(在实际生活中几乎无法测量)但它是存在的。我的意思是运行时零成本。不仅是LLVM,还有GCC,我相信所有其他人都在编译时为支持它的平台生成处理。这样,在输入
try
块时就不会设置恢复点。如果是这样的话,我的优化就不会在循环的每次迭代中设置恢复点。然而,在零成本的情况下,它在循环之外添加了两到三条指令。这不会减慢运行时间。但是困扰我的是如何计算C++编译器将要使用什么,StjjMP/LojJMP或者编译时生成处理代码。我无法从你的答案或文章中找出最佳的方法。如果目标允许(并且编译器使用)零成本方法,这是否意味着运行时的成本绝对为零,因此不应该使用您原来的双循环优化,因为使用单循环是可以的?@lori:抱歉,这不是一篇“深入”的文章(我不擅长写作)。如果您实际抛出异常,则帧展开会带来成本,这会导致错误的代码局部性和较大的代码大小(抛出会生成大量代码和较小的函数)。使用throw的函数通常不是内联的,如果它经常出现在头文件中,那么二进制大小在所有维度上都会呈指数增长。我想说,例外的使用必须限制在必要的地方。例如,它们用于实现NPTL线程的取消。但是,将其用作控制流是毫无意义的。如果期望很少抛出异常,并且编译器/目标使用零成本方法,那么如果没有抛出异常,则所有成本都将以更大的代码空间支付,但在运行时没有影响?@lori:如果不放在特殊的“冷”部分,则代码大小将更大(默认情况下不会发生)对性能有影响。值得注意的一点是。至少,实际抛出的函数应该是分离的,而不是内联的。在阅读了安腾abi规范后,对大量代码进行了重新分解,并看到性能提高,我倾向于根本不使用异常。在我可以使用的地方,指向本文的链接已经失效。