Friday, June 1, 2012

C++: Exceptions thrown from shared library cannot be caught


My program consisted of several shared libraries. An exception class ExceptionA was defined in the shared library libBasic.so. It was thrown from the shared library libA.so in some conditions. I intended to catch it in another shared library libB.so but failed.

The source code looked flawless. I struggled for quite a while and decided to link everything as static libraries. It worked.

The compiler was gcc. I did a lot of Google search on gcc/exception/c++/shared library. There were not too many results but gcc did have issues in exceptions across shared libraries. I tried the different solutions mentioned in those articles -- link options, attributes, dlopen() flags. No luck.

It finally turned out that inline implementation of the exception class is the root cause. As all the functions of ExceptionA was declared inline, it had separate type info objects in all the three shared libraries. You could use command nm -C -D ***.so to verify that. Because gcc uses address comparisons, rather than string compares, to determine type equality, the ExceptionA thrown from libA.so was regarded as a different type from ExceptionA in libB.so. Moving all the methods of ExceptionA into the cpp file solved the problem. Now the nm command showed that ExceptionA had the only type info object in libBasic.so.

There are some other reasons that inter shared library exceptions can not be caught --

* Visibility: http://gcc.gnu.org/wiki/Visibility
* dynamic_cast, throw, typeid don't work with shared libraries: http://gcc.gnu.org/faq.html#dso
* dlopen() RTLD_GLOBAL flag: https://issues.apache.org/jira/browse/AXISCPP-533

No comments:

 
Get This <