【问题标题】:throw without arguments for failure signallingthrow 不带参数的失败信号
【发布时间】:2011-02-08 10:25:41
【问题描述】:

如果出现问题并且您不知道如何恢复,是否可以从构造函数中调用 throw;

这个想法是让应用程序崩溃并转储,因为状态是未知的。还是应该始终指定参数?

从MSDN我只发现如果没有参数它会重新抛出,但不知道如果没有初始异常重新抛出会发生什么。

【问题讨论】:

  • 如果您想崩溃,只需abort()assert(false)。这将提供转储(取决于您的系统配置),并且比错误消息更容易混淆,该错误消息指出程序因throw; 而终止,没有事先例外。

标签: c++


【解决方案1】:

如果当前正在处理的没有异常throw; 将导致terminate() being called immediately 并且这将异常结束您的程序。这不是很方便 - 与引发有意义的异常相比,您将获得更少的关于发生了什么的信息。您可以抛出一个有意义的异常,在顶层捕获它(如main()),编写一些诊断程序然后结束程序。

【讨论】:

  • 程序转储有一点优势:可以检查整个程序的状态,并尝试分析系统是如何到达那里的。我倾向于在你能恢复的时候抛出一个异常,在你不能恢复的时候就死掉,这样大部分状态都可以被处理。
  • 嗯,是的,在这种情况下不需要展开堆栈。但是 Terminate 也不会保存堆栈信息,是吗?
【解决方案2】:

没有。 throw; 是一种重新抛出当前异常的特殊语法。只有在 catch 块(或从其中调用的代码)内继续传播异常才有意义。

只需使用:

#include <stdexcept>
...
throw std::runtime_error("some description");

甚至只是

throw "some description";

但后者更难处理,而且通常不受欢迎。

【讨论】:

  • 技术上你可以在任何地方使用throw;
  • 不要使用throw "some description";,你扔的东西应该来自std::exception,否则妖怪会来抓你。
  • @sharptooth: 编辑“只能使用”->“只有有意义”才能正式正确。
【解决方案3】:

ASSERT 可能会让您的生活更容易诊断出问题所在

【讨论】:

  • @Maxim:如果您的测试套件是全面的,那么您不需要在发布版本中进行测试(我通常保留测试但改为抛出......)
  • @Maxim 如果您禁用“发布”构建的断言 - 通常您会得到您应得的:随机程序状态,如果非常幸运的话会崩溃。墨菲定律。
  • @VJo:您没有正确使用断言。你听说过检查错误代码和异常吗?
  • @Maxim 我做到了。断言是为了防止将不可能的参数传递给函数。禁用断言的问题很可能是微优化。顺便说一句,我假设 ASSERT 宏(来自答案)正在引发异常。
  • @VJo:在谷歌上搜索“c++ assert”,然后重新阅读第一个命中。
【解决方案4】:

虽然从技术上讲你可以调用它,但它不会做你想做的事。

最简单的解决方案是致电throw std::runtime_exception("thrown from Foo");,同时会提供一些有关发生情况的反馈。

【讨论】:

  • 只要让你的致命异常类捕获堆栈跟踪。
  • @Maxim:是的,也很方便,事实上我们所有的异常都可以,这样追踪它们就更容易了。
【解决方案5】:

当您说“不知道如何恢复”时,您的意思是我认为此时您不知道如何处理错误?

也许你没有得到例外的意义。您抛出信息:发生异常以及原因。然后调用堆栈展开到可以处理的位置。在那一点上,我们知道如何在可能的情况下恢复代码。

【讨论】:

  • 是的,发生了一些不可能的意外情况,例如第三方库中未记录的错误、内存不足错误、位翻转或类似情况。
【解决方案6】:

从技术上讲,您可以这样做,因为 throw 不带参数且没有活动异常只调用 terminate(),默认情况下调用 abort()。我更喜欢直接致电abort(),它需要较少的认知努力来识别正在发生的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多