尝试块是否必要或甚至有助于“零成本”堆栈展开策略?

时间:2015-03-04 13:53:03

标签: c++ exception gcc try-catch

几分钟前我遇到了“零成本”异常处理这个短语,最后去了解它。我之前在异常vs返回代码上下文中已经看过几次这个短语。以下是“零成本”及其替代“setjmp / longjmp”的简短描述。

https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gnat_ugn_unw/Exception-Handling-Control.html

  

GNAT使用两种方法在运行时处理异常。该    setjmp / longjmp方法在输入带有的框架时保存上下文   异常处理程序。然后,当引发异常时,上下文可以   立即恢复,无需跟踪堆栈帧。   这种方法提供了非常强的快速异常传播,但是介绍了   使用异常处理程序的重大开销,即使没有   异常被提出。

     

另一种方法称为“零成本”异常处理。有了这个   方法,编译器构建静态表来描述异常   范围。输入包含的框架时不需要动态代码   异常处理程序。引发异常时,将使用这些表   控制子程序调用堆栈的后向跟踪以进行定位   必需的异常处理程序。这种方法相当差   异常传播的表现,但没有   如果没有引发异常,则为异常处理程序的开销。

(GNAT是一个Ada编译器,但我猜测上面的解释与语言无关。)

这有助于解释为什么我们首先有try - 处理异常的一些策略需要在进入try块时保存上下文。

零成本策略听起来非常类似于goto风格的清理,当然我们不需要mightgoto块。 try块是否有利于零成本策略?对于使用此策略实现C ++异常的编译器,如果语言允许裸throw Exception();语句,它会有什么不同吗? try只是现代编译器的一种评论形式吗?

根据您构建表的方式,零成本的成本可能取决于catch块的数量和位置,但不取决于try块的数量和位置。

Soapbox:名称“零成本”是荒谬的误导。为什么不把它称为“免费午餐”?

有关:

Why is `try` an explicit keyword?

1 个答案:

答案 0 :(得分:1)

  

try阻止“零成本”堆栈展开策略是否必要或甚至有用?

是的,无论放卷策略的细节如何,都需要try块。抛出异常时,异常机制需要识别最近输入的try块,以便找到该块的关联处理程序。

使用“零成本”策略,为进入和离开块而生成的代码将与常规块相同;它是try块的事实只会影响用于堆栈展开的静态数据。

  

如果语言允许裸throw Exception();语句会有什么不同吗?

语言确实允许这样做。如果有一个合适的处理程序与调用堆栈上的某个try块相关联,则程序跳转到该处理程序;否则,它会调用terminate(),因为没有什么可以处理异常。

  

try块是否有利于零成本策略?

这没有任何意义。他们必须确定要考虑的处理程序集;从这个角度来看,他们通过允许他们首先工作来“使”所有放松策略“受益”。

  

try只是现代编译器的一种评论形式吗?

原则上,这可以在没有关键字来识别块的情况下完成,可能将任何catch块与前面的语句相关联。因此,人们可能会将其视为(相当有用的)文档。