几分钟前我遇到了“零成本”异常处理这个短语,最后去了解它。我之前在异常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:名称“零成本”是荒谬的误导。为什么不把它称为“免费午餐”?
有关:
答案 0 :(得分:1)
try
阻止“零成本”堆栈展开策略是否必要或甚至有用?
是的,无论放卷策略的细节如何,都需要try
块。抛出异常时,异常机制需要识别最近输入的try
块,以便找到该块的关联处理程序。
使用“零成本”策略,为进入和离开块而生成的代码将与常规块相同;它是try
块的事实只会影响用于堆栈展开的静态数据。
如果语言允许裸
throw Exception();
语句会有什么不同吗?
语言确实允许这样做。如果有一个合适的处理程序与调用堆栈上的某个try
块相关联,则程序跳转到该处理程序;否则,它会调用terminate()
,因为没有什么可以处理异常。
try
块是否有利于零成本策略?
这没有任何意义。他们必须确定要考虑的处理程序集;从这个角度来看,他们通过允许他们首先工作来“使”所有放松策略“受益”。
try
只是现代编译器的一种评论形式吗?
原则上,这可以在没有关键字来识别块的情况下完成,可能将任何catch
块与前面的语句相关联。因此,人们可能会将其视为(相当有用的)文档。