【问题标题】:Throwing an exception while handling an exception处理异常时抛出异常
【发布时间】:2013-07-24 05:07:21
【问题描述】:

我正在阅读“C++ 编程语言第 4 版”一书,并且对有关异常处理的段落有疑问:

在某些情况下,必须在短时间内放弃异常处理 微妙的错误处理技术。指导原则是:

  • 在处理异常时不要抛出异常。
  • 不要抛出无法捕获的异常。

如果异常处理实现发现你正在做任何一个,它 将终止您的程序。

谁能给我一个第一种情况的例子?我想到的只有这样的东西,但它是根据 g++ 的有效代码:

try
{
    throw 1;
}
catch(...)
{
    try
    {
        throw 2;
    }
    catch(...)
    {
        cout << "OK";
    }
}

【问题讨论】:

  • 不要仅仅因为它编译就假设某些东西是有效的和/或做你认为的事情! C++undefined behaviour 的概念,大致翻译为“如果你做了一些无效的事情,所有的赌注都关闭了”。它可能会崩溃,它可能会工作,它可能看起来有效,但会将您所有的信用卡号码发送给尼日利亚王子。请注意,我并不是说这种特殊情况是(我认为它不是 UB,只是危险地接近),但不要认为“它已编译,没问题”。
  • 我不能同意其中的第一个,但可以完全同意第二个。有很多次catch-blocks可以抛出异常,包括相同的异常(通过throw;)。
  • 正文继续:请注意,一旦进入 catch 子句,就会立即处理异常。

标签: c++ exception-handling try-catch


【解决方案1】:

这有点误导;只要有另一个处理程序来捕获它,就可以从异常处理程序中抛出(这就是我所理解的“处理异常时”)。

问题是,如果您从堆栈展开期间被销毁的对象的析构函数中抛出异常。那样的话,有两个未处理的异常,通常的异常机制只能处理一个;所以响应是调用terminate

例子:

struct dodgy {~dodgy() {throw "Don't do this!";}};

try {
    dodgy d;
    throw 1;
} catch (...) {
    // Never reached: destroying `d` killed the program.
}

【讨论】:

  • +1 表示多掷环境中的析构函数行为。不经常考虑,但经常是一个问题。写得不错。
  • 谢谢,我还在标准中找到了更详细的解释 - 它是 15.5.1/1。
  • 你可以使用std::uncaught_exception看看抛出异常是否会杀死程序。
  • 我向你保证,我确实在 g++ 4.8.1 中收到了这条消息 - “在抛出 'int' Aborted (core dumped) 的实例后调用终止”
  • @Quentin:谜团解开:我不知道,在 C++11 中,析构函数是隐式声明的 noexcept,除非您提供明确的异常说明符。所以维基是正确的;除非您故意覆盖隐式说明符,否则析构函数不能抛出。血淋淋的细节见 15.4/14。
猜你喜欢
  • 1970-01-01
  • 2011-10-10
  • 2013-05-24
  • 2023-03-06
  • 2011-12-12
  • 2012-04-26
  • 2011-11-23
  • 1970-01-01
  • 2019-07-19
相关资源
最近更新 更多