How is the C++ exception handling runtime implemented?

C++ExceptionError HandlingLanguage Implementation

C++ Problem Overview


I am intrigued by how the C++ exception handling mechanism works. Specifically, where is the exception object stored and how does it propagate through several scopes until it is caught? Is it stored in some global area?

Since this could be compiler specific could somebody explain this in the context of the g++ compiler suite?

C++ Solutions


Solution 1 - C++

Implementations may differ, but there are some basic ideas that follow from requirements.

The exception object itself is an object created in one function, destroyed in a caller thereof. Hence, it's typically not feasible to create the object on the stack. On the other hand, many exception objects are not very big. Ergo, one can create e.g a 32 byte buffer and overflow to heap if a bigger exception object is actually needed.

As for the actual transfer of control, two strategies exist. One is to record enough information in the stack itself to unwind the stack. This is basically a list of destructors to run and exception handlers that might catch the exception. When an exception happens, run back the stack executing those destructors until you find a matching catch.

The second strategy moves this information into tables outside the stack. Now, when an exception occurs, the call stack is used to find out which scopes are entered but not exited. Those are then looked up in the static tables to determine where the thrown exception will be handled, and which destructors run in between. This means there is less exception overhead on the stack; return addresses are needed anyway. The tables are extra data, but the compiler can put them in a demand-loaded segment of the program.

Solution 2 - C++

This is defined in 15.1 Throwing an exception of the standard.

The throw creates a temporary object.
How the memory for this temporary object is allocated is unspecified.

After creation of the temporary object control is passed to the closest handler in the call stack. unwinding the stack between throw and catch point. As the stack is unwind any stack variables are destroyed in reverse order of creation.

Unless the exception is re-thrown the temporary is destroyed at the end of the handler where it was caught.

Note: If you catch by reference the reference will refer to the temporary, If you catch by value the temporary object is copied into the value (and thus requires a copy constructor).

Advice from S.Meyers (Catch by const reference).

try
{
    // do stuff
}
catch(MyException const& x)
{
}
catch(std::exception const& x)
{
}

Solution 3 - C++

You could take a look here for a detailed explanation.

It may also help to take a look at a trick used in plain C to implement some basic sort of exception handling. This entails using setjmp() and longjmp() in the following manner: the former saves the stack in order to mark the exception handler (like "catch"), while the latter is used to "throw" a value. The "thrown" value is seen as if it has been returned from a called function. The "try block" ends when setjmp() is called again or when the function returns.

Solution 4 - C++

I know this is an old question, but there's a very good exposition, explaining both the methods used in each of gcc and VC here: http://www.hexblog.com/wp-content/uploads/2012/06/Recon-2012-Skochinsky-Compiler-Internals.pdf

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionpjayView Question on Stackoverflow
Solution 1 - C++MSaltersView Answer on Stackoverflow
Solution 2 - C++Martin YorkView Answer on Stackoverflow
Solution 3 - C++Eduard - Gabriel MunteanuView Answer on Stackoverflow
Solution 4 - C++Jules MayView Answer on Stackoverflow