I have a project with 2 static libraries.
Library A contains some generic tools I use in most of my project.
Library B contains some specific uses of Library A for my project.
Library A has a vector V of a type T.
Vector V is declared in library B as extern.
V is loaded by library A with elements of type T used in most of my projects, and loaded by library B with elements of type T specific to this project.
To ensure that my vector is filled before any user code (before main()), the loading of V is done by calls to V.push_back(T) in constructors of "initializer objects", and those objects are instantiated as global variables, so their contructors are called before main().
To sum up, I have code like that :
A.lib :
Std::vector<T> tvector
Class TVectorInitializer{
TVectorInitializer(){
T t1, t2 ;
...assignment of T elements...
tvector.push_back(t1) ;
tvector.push_back(t2);
}
~TVectorInitializer(){};
};
TVectorInitializer1 tv1;
B.lib :
Extern Std::vector<T> tvector
Class TVectorInitializer2{
TVectorInitializer2(){
T t3, t4;
...assignment of T elements...
tvector.push_back(t3) ;
tvector.push_back(t4);
}
~TVectorInitializer2(){};
};
TVectorinitializer2 tvi2;
Both initializer objects are constructed before main in my project, so all items are loaded in V. However, the operation is not done in the correct order. The elements T3, T4 of B.lib are first added to tvector, and only after, the vector is constructed and the elements T1, T2 are added from A.lib.
How can my code call the push_back() method of the vector before having constructed it? Does the B lib assume that it is already constructed because it is declared as extern in B scope?
This is the "static initialization order fiasco". What's happening is your global 'tvi2' object is being constructed before your global 'tvector' object.
Basically the first thing the program does at startup is it constructs all global objects. However the order in which they're constructed is not guaranteed. So you'll get hosed if you have globals interdepend on each other like this.
One way to side-step this is to use the "construct on first use" technique.
Now tvector is a function which returns a local static object, rather than a global object. This ensures that 'the_vector' will be constructed on first use, which guarantees that it will be constructed before you add elements to it.
Thanks, it worked perfectly! I was aware of the initialization order problem, but i mainly found strange that the compiler allowed to access a method on a static object before constructing it.
Hope it helps others
In case others read, the C++ standard guarantees that if A and B are statics declared in the same translation unit
(read: cpp file), then A and B are initialized in the order of their declaration. However, if C and D are statics
declared in different translation units (read: different cpp files), then the order of initialization of C and D is not
specified/defined -- it is compiler dependent. This latter case is what is happening here.