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:
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:
f();
and uncomment g();
(not catching the exception), you have hint of stack not being unwoundSo, 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?
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.
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.
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.
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.
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 tostd::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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With