The issue that you are facing is caused by the static initialization order fiasco, which says in short that the order of construction and destruction of static and global variables across different compilation units is unspecified.
The fact that in your case the problem occurs (i.e. order of initialization causes a problem) only in a certain environment and not in another, is exactly what unspecified order means: it is affected by the order of compilation and it may be affected by compiler optimizations and other considerations that may be related to the environment. It may even be initialized concurrently in different threads (see: C++ spec [stmt.dcl] and a reason for why and when that may happen at the proper section in the original working doc dealing with that issue).
Is there a solution for the static initialization order fiasco?
Yes, there are several possible solutions.
The first solution may be a redesign.
Redesign option 1 - change the code so you would not have more than a single global object.
You may handle all the other "globals" inside the single actual global object. There are libraries which handle singletons in such a way, managing under the hood all singletons inside a single global SingletonManager. But since such a change may require quite a lot code changes, with the accompanied risks, you may need to consider the other options.
Redesign option 2 - use static or global functions instead of global variables - once your globals are retrieved from a static or global functions like the below the order of initialization is solved:
Boo& get_global_boo() {
static Boo b(get_global_foo());
return b;
}
Foo& get_global_foo() {
static Foo f(42);
return f;
}
You may compare this code example facing the initialization order fiasco to one which solves the issue with static methods. This approach is sometimes called "Meyers Singleton" on behalf of Scott Meyers who discussed this approach in his book "More Effective C++".
More on that approach can be found here and here.
Redesign option 3 - a more simple redesign approach would be to move all global variables to a single compilation unit. This approach requires less changes in your code and is probably less risky. But is not always possible.
Another solution is to use compiler specific options for setting the order of initialization - managing manually the order of static and global initializations can be done in Visual Studio with init_seg
- a Visual Studio specific pragma
allowing the developer to control the order of initializations. See: MSDN documentation and this blog post.
GCC has also its own attribute for that purpose - init_priority
.
Last option is the best but most complicated - you may follow the way the C++ library does the trick for std::cout
, which is a global object, yet guaranteed to be initialized whenever you need it, even in global context. This is done with the nifty counter idiom. You may read more about this idiom in the C++ Idioms wiki and also at this SO question. Note that the nifty counter idiom is not a solution for all cases of std::cout
usage in global context, and in quite rare cases there is a need to "help" it work correctly with a statement like: static std::ios_base::Init force_init;
see this SO post on that.
For an additional discussion of the issue see also: Static variables initialisation order