static constructors and symbol bindings in (2)

Rod Evans suggested me NOT to use "-Bdirect" for a C++ library. And thanks a lot to Stephen Clamage (ANSI C++ chairman), taught me to use "-instlib" option of CC. 

$ CC -flags
... ...
-instlib=<library>    Inhibit generation of instances already in <library>
... ...

The option causes the the compiler to scan the named library for template instances (and inline functions generated out of line), then omit generating them in the current .o file. Therefore, by specifying -instlib=./ when building, the instantiated template "std::basic_string<unsigned int> str" would not be linked into So that the cyclic dependencies would not happen.

I added this option in the of, and it worked as expected.

+im_scim_la_CXXFLAGS=@GTK2_CFLAGS@ \
+                   -instlib=$(top_builddir)/src/.libs/

You could refer to [osol-tools-linking] thread for details.

static constructors and symbol bindings in


#include <stdio.h>
#include <stdlib.h>
#include <string>

class Bar
        std::basic_string<unsigned int> name;
        char *buf;
        Bar ()  { buf = new char[10]; buf[9] = '';}
        ~Bar () { delete [] buf; }


static Bar bar;

void __initialize_libbase ()
        printf ("%s\n", bar.buf);


#include <string>
#include "libbase.h"

class Foo {
        std::basic_string<unsigned int> str;
        Foo () { __initialize_libbase (); }
        void test () { printf ("test ()!\n"); }

static Foo foo;


#include <dlfcn.h>
#include <link.h>

int main (int argc, char **argv)
        dlopen ("./", RTLD_LAZY|RTLD_GLOBAL);

When the main program call dlopen (""), it resolves the dependencies, then adds in the initialization sequence ahead of (the order is reversed). And the static constructors in a shared library are in the .init routine.

In our case, while it's trying to initialize the static object "bar", it finds there is a symbol "xxx::__null_string_ref_rep<xxx>" (introduced by std::basic_string<unsigned int>), then looks up this symbol in loaded libraries. Firstly, it looks up the symbol in main program, then in, then finds matched one in, and stops to move on (actually, also has this symbol). Then it tries to initialize, and initializes the static object "foo". Unfortunately, the constructor of Foo calls a external function in libbase, and this function accesses the static instance "bar", which is not initialized yet (the "buf" is not allocated).

So, it cores. That's the root cause why Scim GtkIMModule makes applications core.

While, if you added a main() in libtest.cpp, and compile it to an executable program, this problem would not happen. If you changed the flag from RTLD_LAZY to RTLD_NOW, this problem would not happen either. To resolve this, add -Bdirect option when you link the library. Refer to the new "Direct Binding" chapter of "Linker and Libraries guide".

And I need thank Rod Evans, he taught me to set LD_DEBUG env variable to show the debug informations. You could refer to [osol-tools-linking] thread for details.