So imagine you’ve got an exception you’re catching and then in the catch you write to a log file that some exception occurred. Then you want your program to continue, so you have to make sure that certain invariants are still in a a good state. However what actually occurs in the system after the exception was “handled” by a catch?
The stack has been unwound at that point so how does it get to restore it’s state?
“Stack unwinding” means that all scopes between
throw and the matching
catch clause are left, calling destructors for all automatic objects in those scopes, pretty much in the same way function scopes are left when you return from a function.
Nothing else “special” is done, the scope of a
catch clause is a normal scope, and leaving it is no different from leaving the scope of an
If you need to make sure certain invariants still hold, you need to program the code changing them in a thread-safe manner. Dave Abrahams wrote a classic on the different levels of exception safety, you might want to read that. Basically, you will have to consequently employ RAII in order to be on the safe side when exceptions are thrown.
Only objects created inside the
try will have been destroyed during unwinding. It’s up to you to write a program in such way that if an exception occurs program state stays consistent – that’s called exception safety.
C++ doesn’t care – it unwinds stack, then passes control into an appropriate
catch, then control flow continues normally.
It is up to you to ensure that the application is recovered into a stable state after catching the exception. Usually it is achieved by “forgetting” whatever operation or change(s) produced the exception, and starting afresh on a higher level.
This includes ensuring that any resources allocated during the chain of events leading to the exception gets properly released. In C++, the standard idiom to ensure this is RAII.
For example, if an error occurs while processing a request in a web server, it generates an exception in some lower level function, which gets caught in a higher level class (possibly right in the top level request handler). Usually the best possible thing to do is to roll back any changes done and free any resources allocated so far related to the actual request, and return an appropriate error message to the client. Changes may include DB transactions, file writes, etc – one must implement all these in an exception safe manner. Databases typically have built in transactions to deal with this; with other resources it may be more tricky.