Incompatible C++ versions/wrapping C++ in C?

David Hemming
Tue Oct 1 02:53:00 GMT 2002

I'm interested in finding a robust solution to a
number of bugs relating to incompatible C++ library
ABI versions affecting Sun's Java implementation. Some
relevent bug reports are here:

(I'm only addressing the first of these here, with the
second really being Sun's problem...)

The basic issue is that an application (in this case
the Java VM itself) is built to require the
compatibility version of the C++ support library I am building a shared
library with a pure C interface, but the functions
make internal use of full C++ functionality. (They may
throw exceptions internally, but of course they are
all caught and do not propagate through the C
interface, which has other error reporting channels.)
This shared library is built with some version of gcc
(RedHat gcc 2.96 by default, but stock 3.1 or 3.2
would be nice) and linked against the appropriate
version of the C++ support library
( for 2.96). As a result, when
the application loads the shared library and the
shared library throws an exception internally, a C++
support function (__rethrow) is called and the whole
process dies with a SEGV. I expect that this is a
result of a symbol conflict or ABI incompatibility
between the two versions of the support library (which
is understandable).

There are a couple of workarounds suggested by Sun in
the above bug report, both of which involve tricking
the executable into loading the new version of the
support library and not the compatibility version.
This seems very nasty to me, and will not be an
acceptable solution in all situations. (As a sidenote,
where precisely are the differences between these two
versions noted? Can I assure that this change is

My expectation was that I could simply statically link
the C++ libraries within my shared library, producing
what looked to the application and the dynamic loader
to be a pure C library. Specifying -static to the
linker resulted in a shared library which didn't
*appear* to depend on any other libraries, but the
problems remained. I've also tried running the library
through a version script to tag all the symbols that
don't need to be exported as local. I'm left with a
library whose dynamic symbol table contains my own
entry points (just one, in the simple test), a few
local weak references to pthread functions (what is
the impact of these?), and absolutely nothing else--
no undefined symbols and no global symbols hanging
around to cause conflicts.
With these options in place, I *am* able to avoid
symbol conflicts for my own custom symbols (I've
managed to build an app which dlopens a shared library
where both the app and the shared library
independently depend on yet another library; I am able
to get the main app to call a function in one version
of this extra library and the shared library to call
the same function in a different version.), but this
only makes the JNI loading worse-- the statically
linked shared library causes the VM to abort on the
first call the library instead of when the first
exception is thrown (presumably because it's no longer
doing lazy symbol resolution).

I'm stumped.

What exactly *are* ld and doing to cause these
problems? My understanding of the load and relocation
process was that a clean "nm -D" assured protection
from these kinds of dynamic linking issues, and that
exporting a pure C interface would free you from
worries about C++ ABI changes...

Is there magic in these tools to help with language
support functions?

What is the correct procedure to build a fully
self-sufficient shared library with a pure C
interface, completely hiding away the fact that the
implementation involves C++?

Do you Yahoo!?
New DSL Internet Access from SBC & Yahoo!

More information about the Gcc-help mailing list