【问题标题】:C++ - catching a double exceptionC++ - 捕获双重异常
【发布时间】:2018-11-29 10:37:45
【问题描述】:

我有以下代码:

#include <iostream>
using namespace std;

class A {
public:
    A()  { cout << "A::A()" << endl;}
    ~A() { cout << "A::~A()" << endl; throw "A::exception";}
};

class B {
public:
    B()  { cout << "B::B()" << endl; throw "B::exception";}
    ~B() { cout << "B::~B()";}
};

int main() {
    try {
        cout << "Entering try...catch block" << endl;
        A   objectA;
        B   objectB;
        cout << "Exiting try...catch block" << endl;
    } catch (char const * ex) {
        cout << ex << endl;
    }
    return 0;
}

现在,在陈述问题之前,我想指出这段代码是不好的做法(例如,从构造函数中抛出异常将导致对象没有被完全创建,因此不会调用析构函数,这可能会导致内存泄漏或其他问题)。

现在,主要的顺序是这样的:

  1. 正在打印"Entering try...catch block"

  2. 调用A的构造函数,打印"A::A()"

  3. 调用B的构造函数,打印"B::B()",并抛出异常。

  4. 抛出异常,"Exiting try...catch block"不会被打印。块被退出,所以A的析构函数被调用。

  5. A 的析构函数打印"A::~A()" 并引发另一个异常。

第二个异常(在 5 中)导致 main 在进入 catch 块之前抛出异常。

我的问题是 - 有没有办法在不改变类 A,B 的情况下捕获主要的第二个异常?

我尝试用另一个 try-catch 块包围整个 try-catch 块和 catch 块内部,但没有成功。

谢谢。

【问题讨论】:

  • 在堆栈展开时抛出析构函数会导致程序终止,抛出析构函数是一个非常不好的习惯
  • 任何时候都只能有一个活动异常。
  • 次要注意:在构造函数中抛出异常 - 通常 - 绝对没问题。
  • 顺便说一句。从构造函数中抛出并不坏,它几乎是唯一表明构造出现问题的方法。但是,如果您使用原始指针,那么您应该注意它们。
  • 只是一个练习,您可以使用内部try {B objectB;} catch(...){} 并分别捕获该异常。不过还是比较有用的。

标签: c++ exception exception-handling destructor constructor-exception


【解决方案1】:

来自cppreference.com

与任何其他函数一样,析构函数可以通过抛出异常来终止 [...] 但是如果在堆栈展开期间恰好调用了此析构函数,则会调用 std::terminate

因此,尝试从~A() 引发异常不会导致引发第二个异常;它导致程序被终止。如果您需要“捕捉”这个“第二个异常”,则需要干预the termination handler。或者您可以找到一种不在析构函数中引发异常的方法。从 cppreference.com 继续:

虽然std::uncaught_exception 有时可用于检测正在进行的堆栈展开,但通常认为允许任何析构函数通过抛出异常来终止是不好的做法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    • 2012-09-22
    • 2016-11-11
    相关资源
    最近更新 更多