views:

255

answers:

2

I'm trying to debug a C++ program compiled with GCC that freezes at startup. GCC mutex protects function's static local variables, and it appears that waiting to acquire such a lock is why it freezes. How this happens is rather confusing. First module A's static initialization occurs (there are __static_init functions GCC invokes that are visible in the backtrace), which calls a function Foo(), that has a static local variable. The static local variable is an object who's constructor calls through several layers of functions, then suddenly the backtrace has a few ??'s, and then it's is in the static initialization of a second module B (the __static functions occur all over again), which then calls Foo(), but since Foo() never returned the first time the mutex on the local static variable is still set, and it locks.

How can one static init trigger another? My first theory was shared libraries -- that module A would be calling some function in module B that would cause module B to load, thus triggering B's static init, but that doesn't appear to be the case. Module A doesn't use module B at all. So I have a second (and horrifying) guess. Say that:

  1. Module A uses some templated function or a function in a templated class, e.g. foo<int>::bar()

  2. Module B also uses foo<int>::bar()

  3. Module A doesn't depend on module B at all

  4. At link time, the linker has two instances of foo<int>::bar(), but this is OK because template functions are marked as weak symbols...

  5. At runtime, module A calls foo<int>::bar, and the static init of module B is triggered, even though module B doesn't depend on module A! Why? Because the linker decided to go with module B's instance of foo::bar instead of module A's instance at link time.

Is this particular scenario valid? Or should one module's static init never trigger static init in another module?

Clarification: GCC creates the mutexes automatically to guard any function static variable. I'm not doing anything with mutexes myself. It's GCC's way of making function static variables thread safe.

Update: I know that static initialization is not defined between translation units and that I shouldn't depend on an order. But I'm curious if this is normal behavior as a clue towards debugging the problem. Is it normal for a compiler to generate code that does this or is it potentially indicative of a bug in GCC?

+2  A: 

Bill pulls out Effective C++ Item 4 :

the order of initialization of nonlocal static objects defined in different translation units is undefined

Simply put, the compiler is allowed to do whatever it wants.

Billy ONeal
I know ;) See my update.
Joseph Garvin
+2  A: 

Welcome to the "static initialization order fiasco". You should probably just read that entire article, as it will describe (in detail) how you may be running into this issue & how to fix it.

Agoln
Thanks for the link, but I'm well aware. I'm asking if this is normal behavior for a compiler and/or specifically GCC.
Joseph Garvin