Question

In C++, how can I detect in the body of my destructor whether the stack is being unwound due to an exception being thrown? Once detected, can I get a reference to the active exception?

I ask because I'd like to add some debugging code that explains why a certain situation may arise and whether it is due to exceptions or not.

Was it helpful?

Solution

std::uncaught_exception tells you whether the stack is being unwound due to an exception being thrown, which is what you asked.

However, it doesn't tell you what you probably want to know: whether the object whose destructor you call it from, is in the part of the stack that's being unwound, or the part of the stack that's being destroyed normally due to non-exceptionally exiting a scope beneath some other destructor that is part of the unwind:

struct A {
    ~A();
};

struct B {
    ~B();
}

int main() {
    try {
        A a;
        throw 1;
    } catch(...) {}
}

A::~A() {
    std::uncaught_exception(); // true
    B b;
}

B::~B() {
    std::uncaught_exception(); // also true, but "b" isn't being "unwound",
      // because ~A() returned, it didn't throw.
}

Contrary to what DeadMG and Xeo say, you cannot get a reference to an exception that has not been caught. throw with no operand rethrows the "currently handled exception", that is to say an exception whose catch-handler you are in, or whose catch-handler has called you. It does not rethrow an uncaught exception.

OTHER TIPS

What about C++17's new std::uncaught_exceptions()? I think you can build a code that looks like this:

class ExceptionSentinel
{
    int prev_uncaught;

public:
    ExceptionSentinel() : prev_uncaught(std::uncaught_exceptions()) {}

    ~ExceptionSentinel()
    {
        int cur_uncaught = std::uncaught_exceptions();
        if (cur_uncaught > prev_uncaught)
        {
            // ... ExceptionSentinel is being destructed by an stack unwinding process
        }
        else
        {
            // ... Normal destruction of ExceptionSentinel
        }
    }
};

In this case, std::uncaught_exceptions() tracks the number of uncaught exceptions by the time the code is called. More info can be found on its cppreference page.

There is a std::uncaught_exception() function. However, about the only useful thing you can do to attempt to gain access to the exception object is rethrow it and try to catch it. You should never throw exceptions from any destructor, in general.

In C++, how can I detect in the body of my destructor whether the stack is being unwound due to an exception being thrown?

Not.

Once detected, can I get a reference to the active exception?

No.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top