【问题标题】:Where does execution resume following an exception?异常后在哪里恢复执行?
【发布时间】:2010-12-29 23:45:14
【问题描述】:

一般来说,在抛出并捕获异常后,程序在哪里恢复执行?它是在抛出异常的代码行之后继续,还是在捕获异常的地方继续?此外,这种行为在大多数编程语言中是否一致?

【问题讨论】:

  • 你问的是 Python 还是 C++ - 两者也不是很相似。

标签: c++ python exception


【解决方案1】:

catch块内的代码被执行,原来的执行在catch块之后继续。

【解决方案2】:

在捕获到异常的地方继续执行,即在catch 块的开头,该块专门针对当前异常类型。执行 catch 块,忽略其他 catch 块(将多个 catch 块视为 switch 语句)。在某些语言中,finally 块也可以在catch 之后执行。然后程序继续执行整个try ... catch ... finally ...之后的下一条指令。

你应该注意,如果一个异常没有在一个块中被捕获,异常会被传播到当前函数的调用者,并向上调用堆栈直到catch处理这个异常。在这种情况下,您可以将函数调用想象成一个宏:在调用它的位置插入每个函数的代码,您将清楚地看到每个 try .. catch ... finally ... 块的嵌套。

如果没有异常处理程序,程序通常会崩溃。 (在这一点上,某些语言可能会有所不同)。

执行流的行为在我所知道的每种语言中都是一致的。唯一的区别在于try ... catch ... finally ... 构造:finally 并不存在于每种语言中,某些语言不允许finallycatch 在同一块中(您必须嵌套两个try 到使用 2),某些语言允许捕获所有内容(C++ 中的 catch (...)),而某些语言则不允许。

【讨论】:

  • 问题是在抛出异常并被捕获后程序执行在哪里恢复。显然catch块被执行了。 @theactiveactor 正在寻找的答案是,在 catch 块之后的行继续执行,除非从 catch 块重新抛出异常或从 catch 块中抛出新的异常。
【解决方案3】:

在 catch 块中继续执行(捕获异常的地方)。
这在使用异常的语言中是一致的。

需要注意的重点(尤其是在 C++ 中)
在 throw 和 catch 点之间,堆栈以有序的方式展开,以便在堆栈上创建的所有对象都被正确销毁(以预期的顺序)。这导致了称为 RAII 的技术。

【讨论】:

    【解决方案4】:

    我手边没有 Bjarne Stroustrup 的“设计与进化”副本,但我相信他在那里写了一些关于可恢复异常的经验。他们发现他们使事情变得更难纠正。毕竟,如果某行发生意外错误,您的异常处理程序必须对问题进行充分修补,以允许在不知道上下文的情况下继续执行。这可能是内存不足的错误(尽管此类错误通常是内存分配失控的结果,并且添加更多内存并不能真正解决任何问题),但一般情况下不会。

    因此,在 C++ 和我熟悉的所有语言中,使用 catch 继续执行,并且不会自动返回引发异常的地方。

    【讨论】:

    • 我手头确实有一本 D&E(这可能是我一直以来最喜欢的 CS 书籍)——他引用了 Sun/Xerox PARC 专家的话说:“终止比恢复更可取;这不是意见问题,但需要多年的经验。恢复是诱人的,但无效。”
    【解决方案5】:

    它在异常被捕获的地方恢复。否则,写例外条款的意义何在?

    【讨论】:

    • Perl6 人员正在考虑的一个更深奥的特性是可恢复异常。如果我理解正确,异常处理程序可以选择在引发异常的地方恢复执行。不确定这是否是一件好事(例如:导致人们仍然可以理解的代码)。
    • 我认为抛出的代码至少需要像throw [[returnable]] Type(); 一样发出信号。否则我想这可能会导致一团糟。
    • @~unutbu : 显然 :) 我认为真正的问题是执行被捕获后在哪里恢复。
    • "在 Perl 6 中通过向最外层范围抛出可恢复的控制异常来产生警告,默认情况下会打印警告并通过从异常中提取恢复继续来恢复异常,该异常必须由warn() 函数(或等效函数)。在 Perl 6 中,异常不可恢复,除非异常对象具有 Resumable 角色。" perlcabal.org/syn/S04.html
    • @Moshe Levi,是的,我认为你是对的。我会删除我的答案,如果它不会同时删除 Thilo 关于 Perl 6 的有趣信息。
    猜你喜欢
    • 1970-01-01
    • 2013-05-10
    • 1970-01-01
    • 2011-03-01
    • 2011-03-10
    • 2011-03-07
    • 2015-08-28
    • 1970-01-01
    • 2020-05-19
    相关资源
    最近更新 更多