【问题标题】:How to properly catch std and boost exceptions如何正确捕获 std 和 boost 异常
【发布时间】:2011-12-29 12:12:11
【问题描述】:

请告诉我如何在 boost::exception 中正确使用 try/catch。

这是一个例子

void Settings::init(const std::string &filename)
{
    using boost::property_tree::ptree;
    try 
    {
        read_xml(filename, pt);
    }
    catch(boost::exception const&  ex)
    {
        LOG_FATAL("Can't init settings. %s", /* here is the question */);
    }
}

我也需要 catch std::exception 吗? 我不能让我的应用程序失败,所以我只需要记录所有内容。

统一更新: 我现在也无法理解如何从异常中检索日志记录信息???

【问题讨论】:

  • 是的,我也会在 boost::exception 之后添加 std::exception。我还要添加 catch (...)
  • 如果因为发生错误而引发异常,那么仅仅捕获异常并不能消除错误。您的应用程序仍然失败,您只是更难看到发生了什么。因此,只有在您知道异常指示并能够有意义地处理它们的情况下才能捕获异常
  • @jalf 上面的代码并没有简单地吞下异常。至少有一些日志记录。
  • Guys =) 现在这不是那么重要了。你最好告诉我关于 UPD 的事
  • UPD?什么是 UPD?我认为在一个关于如何正确捕获异常的问题中,讨论应该如何捕获异常对我们来说非常重要。 ;)

标签: c++ boost logging exception-handling


【解决方案1】:

这取决于您在 try 块中运行的代码。如果 read_xml 中的代码可以抛出 std::exception 那么你最好也捕获 std::exception 。如果您不确定,那么同时抓住它们也没什么坏处。

【讨论】:

    【解决方案2】:

    如果你真的想做一些与该类型相关的事情,你应该catch 只使用特殊的异常类型。否则只需使用std::exception。如果你的代码可能会抛出一些不同的东西,而不是捕获... 或在std::exception 之后。

    如果您想处理多个(特殊)异常类型而不是首先处理最明确的。

    【讨论】:

      【解决方案3】:

      std::exception 有一个名为what() 的成员函数,它返回一个const char*可能 解释发生了什么。如果你想记录它(猜测LOG_FATAL 以某种方式包装printf)你可以这样做:

      catch(std::exception const&  ex)
      {
          LOG_FATAL("Can't init settings. %s", ex.what());
      }
      

      对于boost::exception,您可以使用boost::get_error_info 了解更多信息。

      【讨论】:

      • 虽然要从boost::exception 访问what(),但您需要捕获或将dynamic_cast 访问std::exception
      • 除非我弄错了,boost::exception 不会从 std::exception 继承,所以你调用 .what() 的例子是无效的。另外,我相信 std::exception 通常返回一个 const char* 而不是 std::string
      • @obmarg 你错了。 catch(boost::exception const& e){ cout << dynamic_cast<std::exception const&>(e).what(); } 编译并完美运行。
      • @Qix 这些天我没有做足够多的 C++ 来调查,但看起来booost::exception 确实没有从 std::exception 继承:boost.org/doc/libs/1_55_0/libs/exception/doc/…
      • @Qix 啊,当然。遗憾的是,它似乎在任何地方都没有明显的记录(尽管公平地说,我不是很努力)
      【解决方案4】:

      与任何 C++ 一样,以下通用规则适用:

      捕获所有可能抛出的异常,并且只有如果你可以有意义地响应它们。

      您也可以捕获所有其他异常 (...) 并创建日志消息或类似的东西,但是您必须重新抛出它们 (throw;)。如果除了中止某些操作之外您在代码中无能为力,那么您不需要处理异常。让它冒泡到一个可以有意义地使用的地方。

      在您的代码中,您必须至少允许内存分配错误 (std::bad_alloc),因此您可以检查这些错误,如果这有意义的话。但同样,如果您不知道自己捕捉到了什么,那么您将无能为力。

      说你的“程序不能失败”只能意味着这么多。最终,如果您在顶级数据结构中出现分配错误,您可以 做任何事情。我能想象的最好的场景是,如果你的 main 函数循环处理一些数据;在这种情况下,您可以在循环周围放置一个通用的 try 块,如果出现异常,您只需继续下一轮。但我认为这是能够“有意义地处理异常”的一个例子,所以这只是上述情况的一个特例。一般来说,虽然您可能希望将整个 main 函数包装在一个 try 块中,但您只需要接受在最终的包罗万象的情况下,您别无选择,只能中止程序。

      【讨论】:

        【解决方案5】:

        可能回答太晚了......但是

                <...snip...>
                catch (const boost::exception& e)
                {
                    std::string diag = diagnostic_information(e);
                    // display your error message here, then do whatever you need to, e.g.        
                    LOG_FATAL("Can't init settings. %s", diag);
                }
                <...snip...>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-20
          • 2018-07-28
          • 1970-01-01
          相关资源
          最近更新 更多