I'm used to thinking of all initialization of globals/static-class-members as happening before the first line of main(). But I recently read somewhere that the standard allows initialization to happen later to "assist with dynamic loading of modules." I could see this being true when dynamic linking: I wouldn't expect a global initialized in a library to be initialized before I dlopen'ed the library. However, within a grouping of statically linked together translation units (my app's direct .o files) I would find this behavior very unintuitive. Does this only happen lazily when dynamically linking or can it happen at any time? (or was what I read just wrong? ;)
The standard has the following in 3.6.2/3:
It is implementation-defined whether or not the dynamic initialization (8.5, 9.4, 12.1, 12.6.1) of an object of
namespace scope is done before the first statement of main. If the initialization is deferred to some point
in time after the first statement of main, it shall occur before the first use of any function or object defined
in the same translation unit as the object to be initialized.
But o Of course you can never officially tell when the initialization takes place since the initialization will occur before you access the variable! as follows:
// t1.cc
#include <iostream>
int i1 = 0;
int main () {
std::cout << i1 << std::endl
// t2.cc
extern int i1;
int i2 = ++i1;
I can conform that g++ 4.2.4 at least appears to perform the initialization of 'i2' before main.
The problem that one wanted to solve with that rule is the one of dynamic loading. The allowance isn't restricted to dynamic loading and formally could happen for other cases. I don't know an implementation which use it for anything else than dynamic loading.
Let's review a pseudocode:
In DLL:
static int ItsDllVar = 1;
int EXPORTED_FUNCTION() { return ItsDllVar; }
In application:
static int AppVar1 = 2;
static int AppVar2 = EXPORTED_FUNCTION() + AppVar1;
So according to static initializing AppVar2 gets 1+2=3
Lazy initialization applicable for local static variables (regardless of DLL)
int f()
{
static int local_i = 5;//it get's 5 only after visiting f()
return local_i;
}
I think this is what happened in my case with g++ 4.7 and CMake (not sure if this is a relevant detail regarding CMake). I have a code that registers a function in the factory. It relies on the constructor calling from a globally initialized variable.
When this code was in the statically linked library the initialization didn't happen! It is now working fine, when I moved it to the object files that linked directly (i.e., they are not combined into a library first).
So, I suspect that you are correct.
Related
Here is the code:
int factorial(int n)
{
if ( n < 0 ) return -1; //indicates input error
else if ( n == 0 ) return 1;
else return n * factorial(n-1);
}
int const a = 10 ; //static initialization
//10 is known at compile time. Its 10!
int const b = factorial(8); //dynamic initialization
//factorial(8) isn't known at compile time,
//rather it's computed at runtime.
(stolen from here)
So it makes sense to me why b is dynamically initialized and a is statically initialized.
But what if a and b had automatic storage duration(maybe they had been initialized in main()), could you then still call their initialization either static or dynamic? Because, to me, they sound like a more general name for initialization than for example Copy initialization.
Also, I have read this and can anybody tell me why they have not directly explained what static and dynamic initialization are? I mean, it looks like that they only have explained in what situations they happen, but maybe there is a reason why?
cppreference states the initializer may invoke (some intializations, like value initialization etc.), but later in the article, they mention static and dynamic initialization as if those two were more general names for some initializations. This could sound confusing, but here I have illustrated what I understand:
(not the most beautiful thing)
Static and dynamic initialization describe the process of loading a binary and getting to the point when main is ready to run.
static initialization describes the information the compiler can work out at compile time, and allows for fixed values to be stored in the binary so at the point when the binary is loaded by the operating system, it has the correct value.
dynamic initialization describes the code which is inserted by the compiler before main runs, which initializes the information which the compiler was unable to calculate. That may be because it involves code directly, or that it refers to information which was not visible to the compiler at compile time.
But what if a and b had automatic storage duration
The simple case when a is an automatic variable of limited scope.
int a = 12;
This could not be statically initialized, because the compiler will not know where to initialize a, as it would be different each time, and on each thread which called it.
The compiler will be able to initialize a with something like.
mov (_addr_of_a), 12
As _addr_of_a is unknown until runtime, and the value 12 is embedded in the code, a case for statically initializing it would not be done.
More complex cases ...
int a[] = { /* some integer values */ };
This is possibly going to be implemented by the compiler as a mixture of static and dynamic code as below.
static int a_init = { /* some integer values */ };
memcpy( a, a_init, length_in_bytes_of_a );
So some cases there will be "leakage" from static initialization into runtime behaviour.
Dynamic behavior is more problematic - it assumes that a function which does not normally expose its implementation, has both a slow execution time, and is a constexpr to give value to the caching at start of the result. I have not seen this optimization occur.
Static and dynamic initialization are technical terms which describe the process of creating a running program. Similar patterns may exist for local variables, but they would not fall into the technical definition of static and dynamic initialization.
class TestClass
{
public:
int x, y;
TestClass();
};
TestClass::TestClass()
{
cout << "TestClass ctor" << endl;
}
TestClass GlobalTestClass;
int main()
{
cout << "main " << endl;
return 0;
}
In this code as known first output will be "TestClass ctor".
My question: Does the ctor function call codes run before main() (I mean, does entry point change ?) , or right after main() and before the executable statements or is there different mechanism ? (Sorry for English)
The question as stated is not very meaningful, because
main is not the machine code level entry point to the program (main is called by the same code that e.g. executes constructors of non-local static class type variables), and
the notion of “right after main() and before the executable statements” isn't very meaningful: the executable statements are in main.
Generally, in practice you can count on the static variable being initialized before main in your concrete example, but the standard does not guarantee that.
C++11 §3.6.2/4:
” It is implementation-defined whether the dynamic initialization of a non-local variable with static storage
duration is done before the first statement of main. If the initialization is deferred to some point in time
after the first statement of main, it shall occur before the first odr-use (3.2) of any function or variable
defined in the same translation unit as the variable to be initialized.
It's a fine point whether the automatic call of main qualifies as odr-use. I would think not, because one special property of main is that it cannot be called (in valid code), and its address cannot be taken.
Apparently the above wording is in support of dynamically loaded libraries, and constitutes the only support of such libraries.
In particular, I would be wary of using thread local storage with dynamically loaded libraries, at least until I learned more about the guarantees offered by the standard in that respect.
Yes, objects with static storage duration are initialized before main(), so indeed the "entry point" is before main(). See e.g. http://en.cppreference.com/w/cpp/language/storage_duration
In fact (although not recommended), you can run a whole program with a trivial main(){}, by putting everything in global instances.
I'm having some problems initializing static string members in c++. I have several classes and each one is holding several static string members that represent an id. When I am initializing the variables by calling a static function everything is fine. However, when I'd like to assign one variable with the value of another it still holds empty string. What's problem with this code?
std::string A::id()
{
std::stringstream sst;
sst << "id" << i;
i++;
return sst.str();
}
std::string B::str = A::id(); //prints "id0";
std::string C::str = "str"; //prints str
std::string D::str = B::str; //prints "" <-- what's wrong here?
std::string D::str2 = C::str; //prints ""
It appears as if the variables I am referring to (B::str and C::str) havent been initialized yet. But I assume when D::str = B::str is executed C::str is initialized at the latest and therefore D::str should also hold the string "id0".
This is Static Initialization Fiasco.
As per the C++ Standard the initialization order of objects with static storage duration is unspecified if they are declared in different Translation units.
Hence any code that relies on the order of initialization of such objects is bound to fail, and this problem is famously known as The Static Initialization Fiasco in C++.
Your code relies on the condition that Initialization of B::str and C::str happens before D::str, which is not guaranteed by the Standard. Since these 3 static storage duration objects reside in different translation units they might be initialized in Any order.
How to avoid it?
The solution is to use Construct On First Use Idiom,in short it means replacing the global object, with a global function, that returns the object by reference. The object returned by reference should be local static, Since static local objects are constructed the first time control flows over their declaration, the object will be created only on the first call and on every subsequent call the same object will be returned, thus simulating the behavior you need.
This should be an Interesting read:
How do I prevent the "static initialization order fiasco"?
There is no guaranteed order of initialization for static variables. So don't rely on it.
Instead init them with actual literal's, or better yet, init them at run-time when they are really needed.
I noticed that if you initialize a static variable in C++ in code, the initialization only runs the first time you run the function.
That is cool, but how is that implemented? Does it translate to some kind of twisted if statement? (if given a value, then ..)
void go( int x )
{
static int j = x ;
cout << ++j << endl ; // see 6, 7, 8
}
int main()
{
go( 5 ) ;
go( 5 ) ;
go( 5 ) ;
}
Yes, it does normally translate into an implicit if statement with an internal boolean flag. So, in the most basic implementation your declaration normally translates into something like
void go( int x ) {
static int j;
static bool j_initialized;
if (!j_initialized) {
j = x;
j_initialized = true;
}
...
}
On top of that, if your static object has a non-trivial destructor, the language has to obey another rule: such static objects have to be destructed in the reverse order of their construction. Since the construction order is only known at run-time, the destruction order becomes defined at run-time as well. So, every time you construct a local static object with non-trivial destructor, the program has to register it in some kind of linear container, which it will later use to destruct these objects in proper order.
Needless to say, the actual details depend on implementation.
It is worth adding that when it comes to static objects of "primitive" types (like int in your example) initialized with compile-time constants, the compiler is free to initialize that object at startup. You will never notice the difference. However, if you take a more complicated example with a "non-primitive" object
void go( int x ) {
static std::string s = "Hello World!";
...
then the above approach with if is what you should expect to find in the generated code even when the object is initialized with a compile-time constant.
In your case the initializer is not known at compile time, which means that the compiler has to delay the initialization and use that implicit if.
Yes, the compiler usually generates a hidden boolean "has this been initialized?" flag and an if that runs every time the function is executed.
There is more reading material here: How is static variable initialization implemented by the compiler?
While it is indeed "some kind of twisted if", the twist may be more than you imagined...
ZoogieZork's comment on AndreyT's answer touches on an important aspect: the initialisation of static local variables - on some compilers including GCC - is by default thread safe (a compiler command-line option can disable it). Consequently, it's using some inter-thread synchronisation mechanism (a mutex or atomic operation of some kind) which can be relatively slow. If you wouldn't be comfortable - performance wise - with explicit use of such an operation in your function, then you should consider whether there's a lower-impact alternative to the lazy initialisation of the variable (i.e. explicitly construct it in a threadsafe way yourself somewhere just once). Very few functions are so performance sensitive that this matters though - don't let it spoil your day, or make your code more complicated, unless your programs too slow and your profiler's fingering that area.
They are initialized only once because that's what the C++ standard mandates. How this happens is entirely up to compiler vendors. In my experience, a local hidden flag is generated and used by the compiler.
I had a discussion this morning with a colleague about static variable initialization order. He mentioned the Nifty/Schwarz counter and I'm (sort of) puzzled. I understand how it works, but I'm not sure if this is, technically speaking, standard compliant.
Suppose the 3 following files (the first two are copy-pasta'd from More C++ Idioms):
//Stream.hpp
class StreamInitializer;
class Stream {
friend class StreamInitializer;
public:
Stream () {
// Constructor must be called before use.
}
};
static class StreamInitializer {
public:
StreamInitializer ();
~StreamInitializer ();
} initializer; //Note object here in the header.
//Stream.cpp
static int nifty_counter = 0;
// The counter is initialized at load-time i.e.,
// before any of the static objects are initialized.
StreamInitializer::StreamInitializer ()
{
if (0 == nifty_counter++)
{
// Initialize Stream object's static members.
}
}
StreamInitializer::~StreamInitializer ()
{
if (0 == --nifty_counter)
{
// Clean-up.
}
}
// Program.cpp
#include "Stream.hpp" // initializer increments "nifty_counter" from 0 to 1.
// Rest of code...
int main ( int, char ** ) { ... }
... and here lies the problem! There are two static variables:
"nifty_counter" in Stream.cpp; and
"initializer" in Program.cpp.
Since the two variables happen to be in two different compilation units, there is no (AFAIK) official guarantee that nifty_counter is initialized to 0 before initializer's constructor is called.
I can think of two quick solutions as two why this "works":
modern compilers are smart enough to resolve the dependency between the two variables and place the code in the appropriate order in the executable file (highly unlikely);
nifty_counter is actually initialized at "load-time" like the article says and its value is already placed in the "data segment" in the executable file, so it is always initialized "before any code is run" (highly likely).
Both of these seem to me like they depend on some unofficial, yet possible implementation. Is this standard compliant or is this just "so likely to work" that we shouldn't worry about it?
I believe it's guaranteed to work. According to the standard ($3.6.2/1): "Objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other initialization takes place."
Since nifty_counter has static storage duration, it gets initialized before initializer is created, regardless of distribution across translation units.
Edit: After rereading the section in question, and considering input from #Tadeusz Kopec's comment, I'm less certain about whether it's well defined as it stands right now, but it is quite trivial to ensure that it is well-defined: remove the initialization from the definition of nifty_counter, so it looks like:
static int nifty_counter;
Since it has static storage duration, it will be zero-initialized, even without specifying an intializer -- and removing the initializer removes any doubt about any other initialization taking place after the zero-initialization.
I think missing from this example is how the construction of Stream is avoided, this often is non-portable. Besides the nifty counter the initialisers role is to construct something like:
extern Stream in;
Where one compilation unit has the memory associated with that object, whether there is some special constructor before the in-place new operator is used, or in the cases I've seen the memory is allocated in another way to avoid any conflicts. It seems to me that is there is a no-op constructor on this stream then the ordering of whether the initialiser is called first or the no-op constructor is not defined.
To allocate an area of bytes is often non-portable for example for gnu iostream the space for cin is defined as:
typedef char fake_istream[sizeof(istream)] __attribute__ ((aligned(__alignof__(istream))))
...
fake_istream cin;
llvm uses:
_ALIGNAS_TYPE (__stdinbuf<char> ) static char __cin [sizeof(__stdinbuf <char>)];
Both make certain assumption about the space needed for the object. Where the Schwarz Counter initialises with a placement new:
new (&cin) istream(&buf)
Practically this doesn't look that portable.
I've noticed that some compilers like gnu, microsoft and AIX do have compiler extensions to influence static initialiser order:
For Gnu this is: Enable the init-priority with the -f flag and use __attribute__ ((init_priority (n))).
On windows with a microsoft compiler there is a #pragma (http://support.microsoft.com/kb/104248)