Magic in C++ Exceptions

Last week and the early part of this week were spent chasing a bug based around C++ exception handling in g++ generated code. A class designed to be used as an exception was defined in a header file and included two shared libraries, one which called the other. I’ll call f1 the other function and f2 the inner function:

f2(){
throw CustomException();
}

In a different file for a different library.

f1() throw(){
try{
f2();
}catch (CustomException& e){
fixerror();
}
}

However the fixerror codewasn’t called.  Due to the throw() clause on the function header the exception was causing the process to abort with an uncaught exception message.   What caused this?  Turns out it was a lack of run time type information (rtti) on the exception object.  The class we had was a simple wrapper around a return code and a string error message.  Since the class was not designed for extension, none of the methods were virtual.  In order to generate rtti, g++ requires a vtable.  The info is served from a function in the vtable.  The exception mechanism in g++ uses rtti to match the  thrown exception to the handlers for that exception.  While there seems to be a workaround for classes with not rtti, it obviously broke when calculated by two different compilation passes.  The solution was to give our exception a virtual destructor.

I like C++, but there seems to be a fair amount of black magic involved in getting it to work correctly.  My guess is that this mechanism is going to be significantly different in each major compiler.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.