【发布时间】:2010-09-24 00:15:21
【问题描述】:
在 C++ 中,RAII 通常被认为是处理异常的一种优越方法:如果抛出异常,则解除堆栈,调用所有析构函数并清理资源。
但是,这会导致错误报告出现问题。假设一个非常通用的函数失败,堆栈被展开到顶层,我在日志中看到的只是:
无法从套接字读取:连接被对等方重置。
...或任何同样通用的消息。这并没有说明引发异常的上下文。特别是如果我正在运行类似事件队列处理循环的东西。
当然,我可以用 try/catch 块包装对套接字读取的每个调用,捕获异常,用更详细的上下文信息构造一个新的异常并重新抛出它,但这违背了拥有 RAII 的目的,并且是缓慢但肯定会比处理返回错误代码更糟糕。
在标准 C++ 中详细报告错误的更好方法是什么?我也愿意接受涉及 Boost 的建议。
【问题讨论】:
-
这听起来不像是 RAII 的问题,而更像是 C++ 异常对象不提供任何固有上下文的问题;换句话说,您无法在捕获点处获得显示异常最初抛出位置的堆栈跟踪。
-
好吧,既然您对 Boost 持开放态度,请使用Boost.Exception。
-
@GMan 是的,我知道这个库,但它无助于添加中间上下文(我已经可以用标准 C++ 告诉一个 throw 站点和一个 catch 站点)。
-
@Alex B:从某种意义上说,如果你使用 catch-and-throw 选项,那么它会让你的 catch 子句更容易编写。您可以将更多上下文信息填充到现有异常中,而不是构建新异常。
-
您的问题将错误处理中的错误报告和资源管理问题混为一谈。 RAII 仅与资源管理有关。使用异常而不是返回码是为了确保错误能够持续传播,并且函数可以更频繁地返回其语义“结果”。如果您充分利用 RAII,即使在通过返回码处理错误的代码中也会释放资源。通过异常更容易实现这一点,因为您不会意外忘记带有返回码的函数。