In C static / global variables are initialized at zero
before entering main(), and are freed
after leaving main (in practice some shortcuts are taken, but the idea is this). C++ aims to keep the same semantic of C, but there is the added burden of dealing not only with C type variables, but with objects that have a constructor and a destructor that, by definition, must be called at object initialization and freeing. So the natural consequence is that in C++ some user written code (the c'tor function) is executed before entering main and some other (the d'tor function) after main returns. This seemingly innocuous extension to objects of a C semantic has very deep implications. The point is that in C and, for extension, also in C++ there is
no way for the programmer to influence what happens before entering main, in particular, there is no way to determine
in which order the global variables will be initialized: the only guarantee is that all the globals will be initialized before entering main, but order in which this happens is undefined by standard. For C this is not a problem because everything is just set to zero. But for C++ it is.
What happens if in the c'tor of a global variable A is accessed another global variable B that has a non default c'tor ?
If B has been already initialized at the time A c'tor is called everything works as expected, if not than a crash or a not intended behaviour occurs. The real problem is that these kind of bugs are very subtle because the order in which globals are initialized depends on platform/compiler/libraries conditions so can happen that a program compiles and runs fine for me but not for you, for instance because I use MSVC and you gcc, or because I use a library version and you another or for any other reason. The standard explicitly recommends of not relying on a given order of initialization of globals.
The above scenario is much more common than what one would think. For instance a possible tentative solution to the problem posted by Lucas could be:
Code: Select all
#include <iostream>
struct Test {
Test(){ std::cout << "Initialize" << std::endl; }
~Test(){ std::cout << "Cleanup" << std::endl; }
};
Test test;
int main() {
std::cout << "Hello, world!\n";
}
Can you spot the problem here ?
The problem is that std::cout is itself a global object! So std::cout may or may be not already initialized at the time 'test' c'tor is called. And the above code may or may not work.
P.S: Actually the above code always works becasue std::cout is guaranteed to be constructed before the first constructor of a static object is called (
http://en.cppreference.com/w/cpp/io/cout) but this is a very ad-hoc rule introduced in C++11, for instance in C++03 this is not true (
http://stackoverflow.com/questions/8784 ... nitialized).
P.P.S: On the net you can find some 'clever' trick to workaround this issue: do not look at them. Just don't rely on gobal's order of initialization.