stack unwinding
In the stack unwinding section there are the two following paragraphs:-
Once the exception object is constructed, the control flow works backwards (up the call stack) until it reaches the start of a try block, at which point the parameters of all associated catch blocks are compared, in order of appearance, with the type of the exception object to find a match (see try-catch for details on this process). If no match is found, the control flow continues to unwind the stack until the next try block, and so on. If a match is found, the control flow jumps to the matching catch block.
As the control flow moves up the call stack, destructors are invoked for all objects with automatic storage duration that are constructed, but not yet destroyed
Then we have
If an exception is thrown and not caught, including exceptions that escape the initial function of std::thread, the main function, and the constructor or destructor of any static or thread-local objects, then std::terminate is called. It is implementation-defined whether any stack unwinding takes place for uncaught exceptions.
Now I'm a bit confused, at first it says as we move up the stack looking for a try with a matching catch, the destructors are called and then it says if the exception is not caught the destructors are not guaranteed to be called. Which is it? Does the runtime keep track of the destructors that would potentially be called until it finally finds a matching catch and only then it calls them in reverse order of construction? Moreover, are the destructors called before the catch gets executed?
You seem to be under the impression that the destructors are called while searching for a matching catch(). That does not have to be the case.
Destructors from the current location in the program to the matching catch() end up getting called, but that does not need to start happening until the catch is found.
The second block just states that if no catch is found, then the program is allowed to immediately terminate as soon as it makes that determination.
Which is it?
The language itself does not care how an implementation works, only how it behaves. As long as the behavior respects all the requirements, anything is fair game. In this case, it could go either way.
Moreover, are the destructors called before the catch gets executed?
For this part, there is no leeway, they must be executed prior to the code in the catch() statement starting.
Related
I know, marking a function noexcept may be useful in order to get many awesome optimizations [in some cases], such as move semantics, for example. But assume, I have a function in my code that does very critical stuff, and, if this function fails, that would mean that something so bad happened that it is impossible to recover, and the program should be terminated immediately. What if I intentionally mark such a function noexcept even if I admit the probability of exception, just to kill the program if it happens?
Something tells me this is not what it should be used for, but is it a valid use of noexcept?
This is defined behavior, that's specified in the standard. It is informally described as follows:
Whenever an exception is thrown and the search for a handler encounters the outermost block of a non-throwing function, the function std::terminate is called:
There's even a given example, over there, that does exactly that.
Note that a compiler may issue an advisory diagnostic, if it detects this situation, but this is still well-formed code.
such as move semantics
noexcept plays no role in move semantics, except that some e.g. containers try to avoid calling non-noexcept move constructors to provide exception safety guarantees that are otherwise impossible.
something so bad happened that it is impossible to recover, and the program should be terminated immediately.
If an exception isn't caught anywhere up the stack, then this is already exactly what will happen, even if the function is not marked noexcept (except that stack unwinding may or may not happen). If the exception is caught somewhere up the stack, then presumably it can be handled properly and there is no need to immediately terminate.
And if the cause of the exception itself is so critical that the program cannot continue under any circumstances, then an exception should probably not be thrown in the first place. The program should call std::abort or something similar right there at the site causing the problem.
But sure, if you think immediate termination is necessary, then mark it noexcept. I would however still explicitly catch all exceptions with a catch(...) handler in the function and call std::terminate or std::abort manually, so it is clear to a reader and to tools that this is intended behavior. (In this case the stack is unwound up to the handler.)
Is my code ill-formed if I intentionally mark a function [that I know may probably throw] noexcept to terminate immediately in case of exception?
No, letting an exception escape a noexcept function is perfectly fine. It has defined behavior: std::terminate will be called to terminate the program via the currently set terminate handler (and also may or may not unwind the stack beforehand, potentially only partially, including up to the noexcept function).
Suppose I am doing something like:
try
{
do_job();
}
catch(...)
{
std::cout << "GUI is running so we won't terminate and raise a clear error here instead" << std::endl;
};
When calling a failing do_job some static variables/classes are initiated, are they "destroyed" after the catch? If not how to handle this please (i.e. memory allocated to statics)?
My generic problem is: I am having a GUI looping to display stuff to the user, say a game, if an error occur, the program will call std::termniate() I guess, or something similar, but I will find myself in the lovely file <abort>, the GUI then is crached, how can I handle this and reset static variables created when do_job is called please? Shoud I just let them initiated? The user in this case might change mind and not even use the static variables that have been created, so they are there with no use taking memory?
Static storage duration variables, if they have been successfully initialized, will always be destroyed at normal program termination, not earlier.
If a static variable wasn't successfully initialized then it will not be destroyed.
In any case there is nothing for you to take care of under normal conditions. In particular when throwing from do_job, either the static has been fully initialized at the point of the throw or it hasn't been. In the former case it will be destroyed at normal program termination, in the latter case it doesn't need to be destroyed.
In the situation of a std::terminate call, it looks different. It is called under abnormal conditions, such as if an exception is uncaught or an exception thrown while stack unwinding is in progress or an exception escapes a noexcept function.
The default std::terminate handler will call std::abort which abnormally terminates the program and explicitly does not destruct any static storage duration objects. The program just abruptly terminates without any chance to execute any further instructions (except maybe for a SIGABRT handler).
The std::terminate handler can be replaced, but the conditions under which std::terminate is called don't really allow for normal program termination and surely not for sensible continuation of program execution.
The best solution is to not let the abnormal conditions causing it to be called happen. Make sure to not let exceptions escape from main, destructors or noexcept functions. (There are more sources of std::terminate calls. All of them should be avoided.)
When calling a failing do_job some static variables/classes are initiated, are they "destroyed" after the catch?
Variables with static storage duration are destroyed after main returns (either normally, or call to std::exit).
I started to learn the subject of exceptions in C++.
I encountered the term "stack unwinding" which means, to my understanding,
that whenever exception is thrown, and there is no catch block inside the "throwing function", the function stack will "unwind", and by this all local object's d'tor will be called (and the same will also happen in the outer functions untill a suitable catch block will be encountered).
My question:
suppose the exception was thrown inside a try block with suitable following catch,
will the d'tor will be called for all objects defined inside the try block?
or to all objects defined in the try block until the exception occured? or to no object at all, and they will "wait" for the function to exit?
The semantics is that any local variable declared in a block should be destroyed when the control leaves the block (a function is a named block with parameters that are local variables). So when you leave a try-block any locally created variable will be destroyed and its appropriate dtor called. Everything that was created is destroyed, if something was not created, it simply cannot be destroyed. The only thing that is not destroyed is the exception objet itself if it is thrown (of course).
From the C++ spec:
15.2 Constructors and destructors 1. As control passes from the point where an exception is thrown to a
handler, destructors are invoked for all automatic objects constructed
since the try block was entered. The automatic objects are destroyed
in the reverse order of the completion of their construction
15.2 Constructors and destructors 3. The process of calling destructors for automatic objects constructed
on the path from a try block to the point where an exception is thrown
is called “stack unwinding.”
In wikipedia we read:
Resource Acquisition Is Initialization RAII is a programming idiom
used in several object-oriented languages like C++, D, Ada and Vala.
The technique was invented by Bjarne Stroustrup to deal with resource
allocation and deallocation in C++. In this language, the only code
that can be guaranteed to be executed after an exception is thrown are
the destructors of objects residing on the stack.
I don't want to be over pedantic, whatever, but I really am not sure how to interpret this. Is this a slip of the tongue or is this correct? Aren't catch handlers guaranteed to be executed at least?
I know about RAII and what it is, I am focused here on this only code that can be guaranteed to be executed (..) are destructors of objects residing on the stack.
Strictly speaking, the quote is already wrong. When an exception is thrown and there's no matching handler for it, terminate can be called without unwinding the stack and calling any destructors. So, the statement that says that "destructors are guaranteed to be executed when an exception is thrown" is wrong.
As for catch handlers themselves, of course, it is only possible to execute a catch handler if the matching catch handler actually exists.
On top of that, even if the handler exists, there are other reasons that can throw a spanner in the works and prematurely terminate the processing of the exception before it reaches the catch handler. For example, it happens when an "unexpected" exception is thrown. If your function exception specification prohibits some specific exception type and an exception of such "prohibited" type attempts to "fly out" of that function, unexpected will be called immediately, instead of transferring control to the handler.
As mentioned in the comments, another typical situation is when new exception is thrown during stack unwinding triggered by a previous exception. This will result in terminate being called.
The only reason why I would say that Wikipedia is correct there is because if the exception causes the entire application to crash and stop execution, then it wouldn't make it down to the "catch" handler. For the most part you can guarantee that the catch clause will be found and executed.
Source: http://msdn.microsoft.com/en-us/library/fk6t46tz.aspx
C++ automagically calls destructors of all local variables in the block in reverse order regardless of whether the block is exited normally (control falls through) or an exception is thrown.
Looks like the term stack unwinding only applies to the latter. How is the former process (the normal exit of the block) called concerning destroying local variables?
An object is automatically destructed when it "goes out of scope". This could be referred to as "automatic storage reclamation", but that actually refers to garbage collection (there are several papers with that phrase in their name that use the term to mean garbage collection). When it is used to ensure proper pairing of open/close, lock/unlock, or other forms of resource acquisition with their appropriate release, then it is known as the design pattern of Resource Acquisition is Initialization (RAII), which is somewhat ironic given that the main aspect of RAII is not the resource initialization or acquisition, but rather its destruction.
Stack unwinding happens in both these cases, it's just that under normal execution the stack is unwound only to the context of the calling method (or block) when the executing method returns (or the block is exited). Local variables are allocated on the stack, so they are cleaned up in reverse order of allocation, and it's this process that is called unwinding. It's no different than processing any other type of data that you'd store in a LIFO structure - e.g. undo, redo.
When an exception is thrown the handler will unwind the stack through through zero or more methods until it finds one that can catch the exception, or until it reaches the top of the stack, at which point the unhandled exception handler will be called.
It seems to be convention to only use the term stack unwinding in the case of exception handling, but it's the same process occurring in each of these cases. The specific case where the stack unwinds due to a method exiting is called returning, there doesn't seem to be any convention for naming what happens when a scoped block of code is exited.
The local variable is destroyed when it goes out of scope. Perhaps the process is called like "going out of scope"?
I'm not sure there is a name for this. Stack variables are so automatic that no one worries about them, ever, not even enough to give a name for this automatic cleanup process.
Call it "going out of scope", I guess.
I've always heard it spoken as "going out of scope" or more precisely "an auto variable going out of scope".
If what you're asking is how the method call is actually implemented in machine code, I would say it would depend on the calling convention used