Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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() {
    try{throw(0);}
    catch(...){}
}

void g() {
    throw(10);
}

int main() {
    S s;
    f();
    //g();
}

Now:

  1. if you run it as-is (catching the exception), you have a hint of the stack unwinding
  2. if you comment f(); and uncomment g(); (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?

like image 744
fedino Avatar asked Oct 10 '16 16:10

fedino


People also ask

What is stack unwinding exception?

When an exception is thrown and control passes from a try block to a handler, the C++ run time calls destructors for all automatic objects constructed since the beginning of the try block. This process is called stack unwinding.

What is the role of stack in exception handling?

In the C++ exception mechanism, control moves from the throw statement to the first catch statement that can handle the thrown type. When the catch statement is reached, all of the automatic variables that are in scope between the throw and catch statements are destroyed in a process that is known as stack unwinding.

What is unwinding in programming?

The stack unwinding is a process where the function call stack entries are removed at runtime. To remove stack elements, we can use exceptions. If an exception is thrown from the inner function, then all of the entries of the stack is removed, and return to the main invoker function.

What is the unwinding of the sequence of method calls typically referred to as?

This process is called stack unwinding. Unwinding the method-call stack means that the method in which the exception was not caught terminates, all local variables in that method are destroyed and control returns to the statement that originally invoked that method.


1 Answers

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 (and any thread functions) in a try {} catch(...) {throw;} block.

like image 194
Nicol Bolas Avatar answered Sep 20 '22 14:09

Nicol Bolas