所以想象一下,你有一个正在捕获的异常,然后在catch中写入一个日志文件,发生了一些异常。然后你希望你的程序继续,所以你必须确保某些不变量仍处于良好状态。然而,在异常被捕获“处理”之后系统中实际发生了什么?
此时堆栈已解除,那么如何恢复它的状态呢?
答案 0 :(得分:5)
“堆栈展开”意味着保留throw
和匹配的catch
子句之间的所有作用域,为这些作用域中的所有自动对象调用析构函数,几乎与函数作用域保留时相同。你从一个函数返回。
其他任何“特殊”都没有完成,catch
子句的范围是正常范围,并且与保留else
子句的范围没有区别。
如果您需要确保某些不变量仍然存在,则需要编写代码以线程安全的方式更改它们。 Dave Abrahams写了 a classic on the different levels of exception safety ,您可能想要阅读。基本上,您必须使用 RAII ,以便在抛出异常时保持安全。
答案 1 :(得分:2)
由您决定在捕获异常后应用程序恢复到稳定状态。通常它是通过“忘记”产生异常的任何操作或变化,并在更高层次重新开始来实现的。
这包括确保在导致异常的事件链期间分配的任何资源得到正确释放。在C ++中,标准习惯用语是RAII。
例如,如果在Web服务器中处理请求时发生错误,它会在某个较低级别的函数中生成异常,该异常会被更高级别的类(可能在顶级请求处理程序中)捕获。通常,最好的做法是回滚所做的任何更改并释放到目前为止分配的与实际请求相关的任何资源,并向客户端返回相应的错误消息。更改可能包括数据库事务,文件写入等 - 必须以异常安全的方式实现所有这些。数据库通常有内置的事务来处理这个问题;与其他资源相比,它可能更棘手。
答案 2 :(得分:2)
在展开期间,只有try
内创建的对象才会被销毁。您可以自行编写程序,如果发生异常,程序状态保持一致 - 称为异常安全。
C ++并不关心 - 它展开堆栈,然后将控制权传递给适当的catch
,然后控制流程继续正常进行。
答案 3 :(得分:1)
这取决于应用程序。异常安全several levels。您描述的级别很难在整个应用程序中实现。
然而,某些代码片段可以通过使用RAII等技术,并通过巧妙地排序操作序列来制作“失败透明”。我可以想象一段代码查询几个网址的数据,例如:当一个网址“抛出”时,其余的网址仍然可以处理。或者它可以重试......
答案 4 :(得分:0)
如果你在每个函数中都有异常处理,你可以在下一个更高级别恢复,但它相当复杂,实际上我主要使用异常来检测尽可能接近源的错误但不使用它们来恢复执行。
另一方面,如果有可预测的错误,可以设计处理它的方案,但对我来说异常被认为是异常,所以我倾向于尝试退出,而不是在日志文件中提供良好的提示。 JM2CW
答案 5 :(得分:0)
它不能。在C ++中,异常不可恢复。也不是大多数 现代语言;一些支持的第一语言 异常确实支持可恢复的异常,并发现它 不是个好主意。
如果您希望能够从某个特定点恢复,那么 必须把你的try / catch块放在那里。如果你只想记录 并继续,不要首先抛出异常。