Monday, October 3, 2011

Android NDK, shared libs, and C++ exceptions

So, I was getting all set to write a nice long post about an issue I've noticed a couple times in different manifestations, the net result of which is that you can't throw a C++ exception across a shared-library boundary in Android NDK code.  However, I just noticed that the reasons for this are summed up quite nicely here:

http://groups.google.com/group/android-ndk/browse_thread/thread/c1c001a95f478400

The one thing I'll add is that I've seen this manifest in two very different ways, but with two different NDK toolchains.  Back before the NDK supported C++ exceptions and STL containers, I saw a similar issue using r3 of CrystaX's custom NDK.  The result was a segfault when such an exception was thrown.  This appeared to be a known issue, so I didn't pursue it further and changed the project I was working on to build with a static library, as both discussions suggest as a temporary workaround.

Later, when the official NDK added support for C++ exceptions and STL containers, I moved to using it instead, and eventually I wrote some code that tried to throw an exception across a shared-library boundary.  The results were somewhat different, though.  Instead of a segfault, the result was that the exception was just not caught, resulting in many minutes of staring at code, wondering if I was losing my mind.  I knew one function was throwing an exception, and I was looking right at the block that caught that same exception.  So, I added a catch (...) {} block and copied some of the code from libstdc++'s implementation of terminate to print out the exception info before dying.  This time the exception was caught.  Even weirder, it still printed out the correct type of the exception, though it didn't seem to be able to use that information to pass the exception to the correct catch block.

Anyways.  As you can see if you read the above link(s), this is all due to libstdc++ (the GNU version, in my case) being linked statically, each shared library having its own copy, and that breaking exception handling somehow.  Static linking of the exception-throwing library indeed solves this for me, but I hope the new version of the NDK with support for the GNU C++ shared libraries comes soon.

In the meantime, if you're going to build a static library with the NDK, you'll need to trick the NDK build system into actually doing something.  Check out this StackOverflow question.