fedino fedino - 13 days ago 5x
C++ Question

Is stack unwinding with exceptions guaranteed by c++ standard?

Concerning the stack unwinding, the c++ standard says:

An exception is considered uncaught after completing the initialization of the exception object ([except.throw]) until completing the activation of a handler for the exception ([except.handle]). This includes stack unwinding.

at par 15.5.3 of the current standard. I was trying to understand what the latest sentence (
This includes stack unwindings
) is referring to:

  • is it supposed that the compiler must take care of unwinding the stack?

  • or, is it saying that it is compiler-dependent whether to unwind or not the stack?

The question arises from the following snippet:

#include <iostream>
#include <exception>

struct S{
S() { std::cout << " S constructor" << std::endl; }
virtual ~S() { std::cout << " S destructor" << std::endl; }

void f() {

void g() {

int main() {
S s;


  1. if you run it as-is (catching the exception), you have a hint of the stack unwinding

  2. if you comment
    and uncomment
    (not catching the exception), you have hint of stack not being unwound

So, the two experiments seem to be in favor of the first bullet above; both clang++ and g++ agree on the result (but it is not a discriminant).

Also, it seems to me very strange that the standard, which is really careful in specifying the object live time and duration is leaving a shadow here.

May anyone clarify? Is stack unwinding for uncaught exceptions guaranteed by the standard? If yes, where? If not, why?


Is stack unwinding for uncaught exceptions guaranteed by the standard?

Stack unwinding is guaranteed to happen only for caught exceptions ([except.handle]/9):

If no matching handler is found, the function std::terminate() is called; whether or not the stack is unwound before this call to std::terminate() is implementation-defined.

So it's implementation-defined, otherwise.

If not, why?

In the event of an uncaught exception, the standard causes std::terminate to be called. That represents the end of the execution of the program. If you have some platform-specific way of logging information about the state of the system at that time, you may not want that state to be disturbed by stack unwinding.

And if you're not doing that... then you don't care either way.

If you truly need the stack to always be unwound, then you can put your main code in a try {} catch(...) {throw;} block.