Do static and dynamic initialization only apply to non-local variables? - c++

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.

Related

What run-time costs are there to initializing a static with a variable value?

In C++, what is the expected runtime cost in a reasonable compiler of initializing a static variable with a variable value as opposed to a constant value?
For example consider this code:
bool foo();
bool baz1() {
const bool value = foo();
static bool alternate1 = value;
static bool alternate2 = false;
// Do something.
return alternate1;
}
What is the expected run-time cost difference between alternate1 and alternate2?
Initialisation from a compile-time constant (alternate 2) will most likely happen during program startup, with no cost each time the function is called.
Thread-safe initialisation of a local static variable will cause the compiler to generate something like this pseudocode:
static bool alternate1;
static bool __initialised = false;
static __lock_type __lock;
if (!__initialised) {
acquire(__lock);
if (!__initialised) {
alternate1 = value;
__initialised = true;
}
release(__lock);
}
So there is likely to be a test of a flag each time the function is called (perhaps involving a memory barrier or other synchronisation primitive), and a further cost of acquiring and releasing a lock the first time.
Note that in your code, foo() is called every time, whether or not the variable is initialised yet. It would only be called the first time, if you changed the initialisation to
static bool alternate1 = foo();
The details are implementation-dependent of course; this is based on my observations of the code produced by GCC.
static variables are initialized at the start of your program, which means the init will only occur once. The cost for just a boolean is very low, and for your alternate1 will be the cost of executing foo(), which in your example is not much, since it's just an empty function.
To generalize, the cost will be the maximum cost of either initializing your basic type (int, float, etc) or the cost of initializing (running the ctor) of any user defined type/library defined type. Any static that is initialized with a function, then the max will be the cost of the function being executed.
It appears that your question is not about a static variable in general, but rather about a static variable declared inside a function.
The additional run-time costs of initializing such variable from a run-time value stem from several sources
Such variable should be initialized only once, when the control passes over its declaration the very first time (if ever). In order to achieve that an additional boolean variable/flag is allocated for each such variable and checked every time the control passes over the declaration. If the flag says that the variable is not initialized yet, it gets initialized.
For those static variables has non-trivial destructors, the language has to guarantee that their destruction order at program termination is the reverse of their construction order. Since the construction order determined at run-time, the program has to prepare a run-time structure to schedule the future destructions. This is also done as part of step 1 for variables with non-trivial destructors: they are registered in a "list" of constructed objects in order of their construction. The "list" is typically implemented as a pre-allocated array (since its maximum size is known at compile time).
In multithreaded configurations the above steps might/will be accompanied with additional locking/unlocking steps.
Since these are all "household" expenses implemented "under the hood", the actual cost might greatly depend on the implementation. See/profile the code your specific compiler generates.
Setting alternate1 value will mean calling the function, and even if the function is returning a static value, you will have to save the stack, call the function, get its return value, restore the stack and assign the value to a variable.
Literally, in the first case you will be executing at least 8 assembly code lines, and in the second one – only one line.

Why doesn't the compiler know the addresses of local variables at compile-time?

What does the following statement mean?
Local and dynamically allocated variables have addresses that are not known by the compiler when the source file is compiled
I used to think that local variables are allocated addresses at compile time, but this address can change when it will go out of scope and then come in scope again during function calling. But the above statement says addresess of local variables are not known by the compiler. Then how are local variables allocated? Why can global variables' addresses be known at compile time??
Also, can you please provide a good link to read how local variables and other are allocated?
Thanks in advance!
The above quote is correct - the compiler typically doesn't know the address of local variables at compile-time. That said, the compiler probably knows the offset from the base of the stack frame at which a local variable will be located, but depending on the depth of the call stack, that might translate into a different address at runtime. As an example, consider this recursive code (which, by the way, is not by any means good code!):
int Factorial(int num) {
int result;
if (num == 0)
result = 1;
else
result = num * Factorial(num - 1);
return result;
}
Depending on the parameter num, this code might end up making several recursive calls, so there will be several copies of result in memory, each holding a different value. Consequently, the compiler can't know where they all will go. However, each instance of result will probably be offset the same amount from the base of the stack frame containing each Factorial invocation, though in theory the compiler might do other things like optimizing this code so that there is only one copy of result.
Typically, compilers allocate local variables by maintaining a model of the stack frame and tracking where the next free location in the stack frame is. That way, local variables can be allocated relative to the start of the stack frame, and when the function is called that relative address can be used, in conjunction with the stack address, to look up the location of that variable in the particular stack frame.
Global variables, on the other hand, can have their addresses known at compile-time. They differ from locals primarily in that there is always one copy of a global variable in a program. Local variables might exist 0 or more times depending on how execution goes. As a result of the fact that there is one unique copy of the global, the compiler can hardcode an address in for it.
As for further reading, if you'd like a fairly in-depth treatment of how a compiler can lay out variables, you may want to pick up a copy of Compilers: Principles, Techniques, and Tools, Second Edition by Aho, Lam, Sethi, and Ullman. Although much of this book concerns other compiler construction techniques, a large section of the book is dedicated to implementing code generation and the optimizations that can be used to improve generated code.
Hope this helps!
In my opinion the statement is not talking about runtime access to variables or scoping, but is trying to say something subtler.
The key here is that its "local and dynamically allocated" and "compile time".
I believe what the statement is saying is that those addresses can not be used as compile time constants. This is in contrast to the address of statically allocated variables, which can be used as compile time constants. One example of this is in templates:
template<int *>
class Klass
{
};
int x;
//OK as it uses address of a static variable;
Klass<&::x> x_klass;
int main()
{
int y;
Klass<&y> y_klass; //NOT OK since y is local.
}
It seems there are some additional constraints on templates that don't allow this to compile:
int main()
{
static int y;
Klass<&y> y_klass;
}
However other contexts that use compile time constants may be able to use &y.
And similarly I'd expect this to be invalid:
static int * p;
int main()
{
p = new int();
Klass<p> p_klass;
}
Since p's data is now dynamically allocated (even though p is static).
Address of dynamic variables are not known for the expected reason,
as they are allocated dynamically from memory pool.
Address of local variables are not known, because they reside on
"stack" memory region. Stack winding-unwinding of a program may
defer based on runtime conditions of the code flow.
For example:
void bar(); // forward declare
void foo ()
{
int i; // 'i' comes before 'j'
bar();
}
void bar ()
{
int j; // 'j' comes before 'i'
foo();
}
int main ()
{
if(...)
foo();
else
bar();
}
The if condition can be true or false and the result is known only at runtime. Based on that int i or int j would take place at appropriate offset on stack.
It's a nice question.
While executing the code, program is loaded into memory. Then the local variable gets the address. At compile time, source code is converted into machine language code so that it can be executed

What makes a static variable initialize only once?

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.

Nifty/Schwarz counter, standard compliant?

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)

How static local POD constants are initialized? Lazily or not?

POD means primitive data type without constructor and destructor.
I am curious, how compilers handle lazy initialization of POD static local variables. What is the implication of lazy initialization if the function are meant to be run inside tight loops in multithreaded applications? These are the possible choices. Which one is better?
void foo_1() {
static const int v[4] = {1, 2, 3, 4};
}
void foo_2() {
const int v[4] = {1, 2, 3, 4};
}
How about this? No lazy initialization, but slightly clumsy syntax?
struct Bar
{
static const int v[4];
void foo_3()
{
// do something
}
};
const int My::v[4] = {1, 2, 3, 4};
When a static variable is initialized with constant data, all compilers that I'm familiar with will initialize the values at compile time so that there is no run time overhead whatsoever.
If the variable isn't static it must be allocated on each function invocation, and the values must be copied into it. I suppose it's possible that the compiler might optimize this into a static if it's a const variable, except that const-ness can be cast away.
In foo_1(), v is initialized sometime before main() starts. In foo_2(), v is created and initialized every time foo_2() is called. Use foo_1() to eliminate that extra cost.
In the second example, Bar::v is also initialized sometime before main().
Performance is more complex than just allocation. For example, you could cause an extra cache line to have to be in cache with the static variable, because it's not contiguous with other local memory that you're using, and increase cache pressure, cache misses, and suchlike. In comparison to this cost, I would say that the incredibly tiny overhead of re-allocating the array on the stack every time would be very trivial. Not just that, but any compiler is excellent at optimizing things like that, whereas it can't do anything about static variables.
In any case, I would suggest that the performance difference between the two is minimal - even for inside a tight loop.
Finally, you may as well use foo_2()- the compiler is perfectly within it's rights to make a variable like that static. As it was initially defined as const, const_casting the const away is undefined behaviour, regardless of whether or not it's static. However, it can't choose to make a static constant non-static, as you could be depending upon the ability to return it's address, for example.
An easy method to find out how variables are initialized is to print an assembly language listing of a function that has static and local variables.
Not all compiler initialize variables in the same method. Here is a common practice:
Before the main() method global variables are initialized by copying a section of values into the variables. Many compilers will place the constants into an area so that the data can be assigned using simple assembly move or copy instructions.
Local variables (variables with local scope) may be initialized upon entering the local scope and before the first statement in the scope is executed. This depends upon many factors, one of them is the constness of the variable.
Constants may be placed directly into the executable code, or they may be a pointer to a value in ROM, or copied into memory or register. This is decided by the compiler for best performance or code size, depending on the compiler's settings.
On the technical side, foo_1 and foo_3 are required to initialize their arrays before any functions, including class constructors, are called. That guarantee is essentially as good as no runtime. And in practice, most implementations don't need any runtime to initialize them.
This guarantee applies only to objects of POD type with static storage duration which are initialized with "constant expressions". A few more contrasting examples:
void foo_4() {
static const int v[4] = { firstv(), 2, 3, 4 };
}
namespace { // anonymous
const int foo_5_data[4] = { firstv(), 2, 3, 4 };
}
void foo_5() {
const int (&v)[4] = foo_5_data;
}
The data for foo_4 is initialized the first time foo_4 is called. (Check your compiler documentation to find out whether this is thread-safe!)
The data for foo_5 is initialized at some time before main() but might be after some other dynamic initializations.
But none of this really answers questions about performance, and I'm not qualified to comment on that. #DeadMG's answer looks helpful.
You have a static initialization in all those cases, all your static variables will be initialized by the virtue of loading data segment into memory. The const in foo_2 can be initialized away if compiler finds it possible.
If you had a dynamic initialization, then initialization of variables in the namespace scope can be deferred until their first use. Similarly, dynamic initialization of local static variables in the scope of function can be performed during the first pass through the function or earlier. Additionally, compiler can statically initialize those variables if it's able to do that. I don't remember the exact verbiage from the Standard.