I have a single instance of a simple POD
a.hpp
class A {
struct Zzz {
A* m_aPtr;
int m_val;
}
static Zzz s_zzz;
};
a.cpp
A::Zzz A::s_zzz;
I expect that both s_zzz.m_aPtr and s_zzz.m_val will be initialized to zeros before any other static initialization in any other compilation unit and it is guaranteed by the language itself. Am I right about it?
Usually I provide default constructors for the structs. Say
A::Zzz::Zzz() :
m_aPtr(0),
m_val(0)
{
}
Will it create initialization order problem or introduce compiler dependencies?
At least in C++0x, you can rely on all zero-initialization being performed before any other initialization code runs.
From the C++0x FCD, section [basic.start.init]
Variables with static storage duration
(3.7.1) or thread storage duration
(3.7.2) shall be zero-initialized
(8.5) before any other initialization
takes place.
If you're considering using this variable from other initialization code, then an explicit constructor would be a big mistake, as it would run sometime mixed in with other initialization code, and overwrite whatever changes have already been made by other initializers.
I expect that both s_zzz.m_aPtr and
s_zzz.m_val will be initialized to
zeros before any other static
initialization in any other
compilation unit and it is guaranteed
by the language itself.
It will be zero-initialized, since it's a static lifetime variable at namespace scope.
That zero-initialization happens before any dynamic initialization (an example of dynamic initializatin is when you some explicit initialization, or the class has a constructor).
The order of zero-initialization between different translation units is not defined, but there's not any way to detect it or rely on it since it happens before anything else, so it doesn't matter.
Re your point 2, it's rather unclear what you're asking about.
But for your static lifetime object, the effect is just that it's first zero-initialized, and then during dynamic initialization your constructor is used to zero it again (although the compiler might be smart enough to optimize away that redundant extra initialization).
Cheers & hth.,
ERRATA: Ben Voigt has provided a convincing example that the last paragraph above is wrong. So please disregard. The presence of the constructor means that the object can be dynamically initialized at some point before, between or after operations that change it, causing rather unpredictable results…
There are no guarantees about initialization order of statics between compilation units (see http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14).
If it has a constructor, it will no longer be a POD, unfortunately.
Static data is always initialised to zero.
No it shouldn't introduce any initialisation problems.
When the application is loaded into memory, the static area is initialised to zero. This is before any code starts to execute.
Related
In C++ I know static and global objects are constructed before the main function. But as you know, in C, there is no such kind initialization procedure before main.
For example, in my code:
int global_int1 = 5;
int global_int2;
static int static_int1 = 4;
static int static_int2;
When are these four variables initialized?
Where values for initialization like 5 and 4 are stored during compilation? How to manage them when initialization?
EDIT:
Clarification of 2nd question.
In my code I use 5 to initialize global_int1, so how can the compiler assign 5 to global_int? For example, maybe the compiler first store the 5 value at somewhere (i.e. a table), and get this value when initialization begins.
As to "How to manage them when initialization?", it is realy vague and I myself does not how to interpret yet. Sometimes, it is not easy to explain a question. Overlook it since I have not mastered the question fully yet.
By static and global objects, I presume you mean objects with
static lifetime defined at namespace scope. When such objects
are defined with local scope, the rules are slightly different.
Formally, C++ initializes such variables in three phases:
1. Zero initialization
2. Static initialization
3. Dynamic initialization
The language also distinguishes between variables which require
dynamic initialization, and those which require static
initialization: all static objects (objects with static
lifetime) are first zero initialized, then objects with static
initialization are initialized, and then dynamic initialization
occurs.
As a simple first approximation, dynamic initialization means
that some code must be executed; typically, static
initialization doesn't. Thus:
extern int f();
int g1 = 42; // static initialization
int g2 = f(); // dynamic initialization
Another approximization would be that static initialization is
what C supports (for variables with static lifetime), dynamic
everything else.
How the compiler does this depends, of course, on the
initialization, but on disk based systems, where the executable
is loaded into memory from disk, the values for static
initialization are part of the image on disk, and loaded
directly by the system from the disk. On a classical Unix
system, global variables would be divided into three "segments":
text:
The code, loaded into a write protected area. Static
variables with `const` types would also be placed here.
data:
Static variables with static initializers.
bss:
Static variables with no-initializer (C and C++) or with dynamic
initialization (C++). The executable contains no image for this
segment, and the system simply sets it all to `0` before
starting your code.
I suspect that a lot of modern systems still use something
similar.
EDIT:
One additional remark: the above refers to C++03. For existing
programs, C++11 probably doesn't change anything, but it does
add constexpr (which means that some user defined functions
can still be static initialization) and thread local variables,
which opens up a whole new can of worms.
Preface: The word "static" has a vast number of different meanings in C++. Don't get confused.
All your objects have static storage duration. That is because they are neither automatic nor dynamic. (Nor thread-local, though thread-local is a bit like static.)
In C++, Static objects are initialized in two phases: static initialization, and dynamic initialization.
Dynamic initialization requires actual code to execute, so this happens for objects that start with a constructor call, or where the initializer is an expression that can only be evaluated at runtime.
Static initialization is when the initializer is known statically and no constructor needs to run. (Static initialization is either zero-initialization or constant-initialization.) This is the case for your int variables with constant initializer, and you are guaranteed that those are indeed initialized in the static phase.
(Static-storage variables with dynamic initialization are also zero-initialzed statically before anything else happens.)
The crucial point is that the static initialization phase doens't "run" at all. The data is there right from the start. That means that there is no "ordering" or any other such dynamic property that concerns static initialization. The initial values are hard-coded into your program binary, if you will.
When are these four variables initialized?
As you say, this happens before program startup, i.e. before main begins. C does not specify it further; in C++, these happen during the static initialisation phase before objects with more complicated constructors or initialisers.
Where values for initialization like 5 and 4 are stored during compilation?
Typically, the non-zero values are stored in a data segment in the program file, while the zero values are in a bss segment which just reserves enough memory for the variables. When the program starts, the data segment is loaded into memory and the bss segment is set to zero. (Of course, the language standard doesn't specify this, so a compiler could do something else, like generate code to initialise each variables before running main).
Paraphrased from the standard:
All variables which do not have dynamic storage duration, do not have thread local storage duration, and are not local, have static storage duration. In other words, all globals have static storage duration.
Static objects with dynamic initialization are not necessarily created before the first statement in the main function. It is implementation defined as to whether these objects are created before the first statement in main, or before the first use of any function or variable defined in the same translation unit as the static variable to be initialized.
So, in your code, global_int1 and static_int1 are definitely initialized before the first statement in main because they are statically initialized. However, global_int2 and static_int2 are dynamically initialized, so their initialization is implementation defined according to the rule I mentioned above.
As for your second point, I'm not sure I understand what you mean. Could you clarify?
Overarching question is: how can a programmer make sure that his non-local static variables are initialized via static initialization and not via dynamic initialization?
As zero-initialization is done always then one should look at the constant initialization.
3.6.2.2 A constant initializer for an object o is an expression that is a constant expression, except that it may also invoke constexpr
constructors for o and its subobjects even if those objects are of
non-literal class types [ Note: such a class may have a non-trivial
destructor —end note ]. Constant initialization is performed:
— if each full-expression (including implicit conversions) that
appears in the initializer of a reference with static or thread
storage duration is a constant expression (5.19) and the reference is
bound to an lvalue designating an object with static storage duration
or to a temporary (see 12.2);
— if an object with static or thread storage duration is initialized
by a constructor call, and if the initialization full-expression is a
constant initializer for the object;
— if an object with static or thread storage duration is not
initialized by a constructor call and if either the object is
value-initialized or every full-expression that appears in its
initializer is a constant expression.
I omitted the reference as it is not important in my case. How I understand the standard is that there are 3 cases:
ctor
no-ctor and value initialization
no-ctor and constant expression
Let's say I have a following class:
struct X {
bool flag = false;
// = {} will break VS2013 CTP so in that case use the
// regular ctor, which sadly still can't be declared constexpr
std::aligned_storage<sizeof(int), alignof(int)>::type storage = {};
};
As far as I can say this class is perfectly valid for constant initialization (each element can be constantly initialized). Is this true?
Does this class require a constexpr constructor?
Is constant initialization guaranteed for C++11 as well as C++98?
Side question: When will the static initialization done in case of so/dll? During the load time, or it might be delayed even further?
It would be good to know the purpose behind this question. And also whether your concern is allocation or specifically initialization.
However, the type of initialization shouldn't matter because the required space is allocated at compile time. Depending on how you define the variable, it will end up either in .bss or .data section.
Initialization, as you know, is only to ensure a specific content in the memory before it is first used. If you do not define a constructor that allocates dynamic memory then there won't be any dynamic allocation (if that is your concern).
For simple constructors, I believe the compiler will generate inline code and use the same to initialize the object at compile time (I am not sure what the standard talks about the same but it is possible that it is tool chain dependent.) With complex constructors, non-local static objects will be initialized when the image is loaded in memory and local static objects will be initialized when the stack frame is loaded. In any cases you should find the object in a known state before first use.
Side question: When will the static initialization done in case of
so/dll? During the load time, or it might be delayed even further?
On Windows, static initialization occurs before before DllMain() is invoked with the DLL loader lock acquired. This severely limits what you can do in the constructors for your static objects. You can't load any other DLLs (LoadLibrary) or call any other function that MIGHT cause a DLL to be loaded, which pretty much rules out anything beyond simple initialization and functions exported by Kernel32.
See the last few paragraphs of the DllMain (MSDN) docs for details.
In this topic they said that zero initialization is not static initialization.
Can anyone explain why?
3.6.2/2 said:
Together, zero-initialization and constant initialization are called
static initialization;
It is definition of Static initialization, means that zero-initialization is static initialization and constant-initialization is static Initialization
This answer assumes that you know what static storage duration means.
In C++03 this is specified as (3.6.2):
Objects with static storage duration (3.7.1) shall be zero-initialized
(8.5) before any other initialization takes place. Zero-initialization
and initialization with a constant expression are collectively called
static initialization; all other initialization is dynamic
initialization.
In practice, a program has different memory segments where it stores variables with static storage duration:
One segment is usually called .bss, where all static storage variables that are initialized to zero are stored.
Another segment is usually called .data, where all static storage variables that are explicitly initialized to a value are stored.
And further, there is a segment called .rodata where all const variables are stored.
(The reason why these are two different segments is mainly program startup performance, you can read more about that here.)
Zero initialization applies to all variables stored in .bss and constant initialization applies to all variables stored in .data. (And perhaps constant initialization applies to .rodata as well, depending on whether your system is RAM-based or if it has true ROM).
Collectively, all of this is called static initialization, since it applies to objects with static storage duration.
You forgot to notify the word "Together", very important in this sentence.
Zero-initialization + constant initialization = static initialization. Is that clearer ?
It's just vocabulary. There are clearly three phases of
initialization (for variables with static lifetime): zero
initialization, initialization using constant expressions, and
dynamic initialization. I find it convenient when talking about
this to use the term static initialization for the second step
(because it does take place statically, without the execution of
any user written code), even if the standard uses a somewhat
different terminology. In the end, it comes down to the same
thing:
int a;
int b = 42;
int c = someFunction();
Formally, all three variables will be zero-initialized. Then
b will be initialized with the constant expression 42; in
all likelyhood, it will never actually be zero-initialized,
because there's no way your code can ever see it before the
constant initialization. Finally, c will be initialized by
calling someFunction().
This order is true regardless of the order of the definitions,
and is guaranteed by the standard.
The post you link to says that zero-initialization is not static initialization. This is correct.
That is very different from zero-initialization is not a static initialization! This is not correct.
I have C++ code which declares static-lifetime variables which are initialized by function calls. The called function constructs a vector instance and calls its push_back method. Is the code risking doom via the C++ static initialization order fiasco? If not, why not?
Supplementary information:
What's the "static initialization order fiasco"?
It's explained in C++ FAQ 10.14
Why would I think use of vector could trigger the fiasco?
It's possible that the vector constructor makes use of the value of another static-lifetime variable initialized dynamically. If so, then there is nothing to ensure that vector's variable is initialized before I use vector in my code. Initializing result (see code below) could end up calling the vector constructor before vector's dependencies are fully initialized, leading to access to uninitialized memory.
What does this code look like anyway?
struct QueryEngine {
QueryEngine(const char *query, string *result_ptr)
: query(query), result_ptr(result_ptr) { }
static void AddQuery(const char *query, string *result_ptr) {
if (pending == NULL)
pending = new vector<QueryEngine>;
pending->push_back(QueryEngine(query, result_ptr));
}
const char *query;
string *result_ptr;
static vector<QueryEngine> *pending;
};
vector<QueryEngine> *QueryEngine::pending = NULL;
void Register(const char *query, string *result_ptr) {
QueryEngine::AddQuery(query, result_ptr);
}
string result = Register("query", &result);
Fortunately, static objects are zero-initialised even before any other initialisation is performed (even before the "true" initialisation of the same objects), so you know that the NULL will be set on that pointer long before Register is first invoked.1
Now, in terms of operating on your vector, it appears that (technically) you could run into such a problem:
[C++11: 17.6.5.9/3]: A C++ standard library function shall not directly or indirectly modify objects (1.10) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function’s non-const arguments, including this.
[C++11: 17.6.5.9/4]: [Note: This means, for example, that implementations can’t use a static object for internal purposes without synchronization because it could cause a data race even in programs that do not explicitly share objects between threads. —end note]
Notice that, although synchronisation is being required in this note, that's been mentioned within a passage that ultimately acknowledges that static implementation details are otherwise allowed.
That being said, it seems like the standard should further state that user code should avoid operating on standard containers during static initialisation, if the intent were that the semantics of such code could not be guaranteed; I'd consider this a defect in the standard, either way. It should be clearer.
1 And it is a NULL pointer, whatever the bit-wise representation of that may be, rather than a blot to all-zero-bits.
vector doesn't depend on anything preventing its use in dynamic initialisation of statics. The only issue with your code is a lack of thread safety - no particular reason to think you should care about that, unless you have statics whose construction spawns threads....
Initializing result (see code below) could end up calling the vector constructor before that class is fully initialized, leading to access to uninitialized memory.
No... initialising result calls AddQuery which checks if (pending == NULL) - the initialisation to NULL will certainly have been done before any dynamic initialisation, per 3.6.2/2:
Constant initialization is performed:
...
— if an object with static or thread storage duration is not initialized by a constructor call and if either the object is value-initialized or every full-expression that appears in its initializer is a constant expression
So even if the result assignment is in a different translation unit it's safe. See 3.6.2/2:
Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. Static initialization shall be performed before any dynamic initialization takes place.
I read several posts on C++ initialization from Google, some of which direct me here on StackOverflow. The concepts I picked from those posts are as follows:
The order of initialization of C++ is:
Zero Initialization;
Static Initialization;
Dynamic Initialization.
Static objects (variables included) are first Zero-initialized, and then Static-initialized.
I have several inquiries as to the initialization issue (storage class issue may be related as well):
Global objects (defined without static keyword) are also static objects, right?
Global objects are also initialized like static objects by two steps like above, right?
What is the Static Initialization? Does it refer to initializing static objects (defined with static keyword)?
I also read that objects defined within block (i.e. in a function) with static keyword is initialized when the execution thread first enters the block! This means that local static objects are not initialized before main function execution. This means they are not initialized as the two steps mentioned above, right?
Dynamic initialization refers to initialization of objects created by new operator, right? It might refer to initialization like myClass obj = myClass(100); or myClass obj = foo();
I have too many inquiries on the initialization and storage class specifier issues. I read the C++2003 Standard document, but cannot find a clear logic since they are scattered throughout the document.
I hope you give me an answer that logically explains the whole map of storage class specifier and initialization. Any reference is welcome!
Code that might explain my question:
class myClass{
public:
int i;
myClass(int j = 10): j(i){}
// other declarations
};
myClass obj1;//global scope
static myClass obj2(2);//file scope
{ //local scope
myClass obj3(3);
static myClass obj4(4);
}
EDIT:
If you think my question is rather tedious, you can help explain your ideas based on the code above.
I read several posts on C++ initialization from Google, some of which direct me here on StackOverflow. The concepts I picked from those posts are as follows:
The order of initialization of C++ is:
Zero Initialization;
Static Initialization;
Dynamic Initialization.
Yes, indeed there are 3 phases (in the Standard). Let us clarify them before continuing:
Zero Initialization: the memory is filled with 0s at the byte level.
Constant Initialization: a pre-computed (compile-time) byte pattern is copied at the memory location of the object
Static Initialization: Zero Initialization followed by Constant Initialization
Dynamic Initialization: a function is executed to initialize the memory
A simple example:
int const i = 5; // constant initialization
int const j = foo(); // dynamic initialization
Static objects (variables included) are first Zero-initialized, and then Static-initialized.
Yes and no.
The Standard mandates that the objects be first zero-initialized and then they are:
constant initialized if possible
dynamically initialized otherwise (the compiler could not compute the memory content at compile-time)
Note: in case of constant initialization, the compiler might omit to first zero-initialized memory following the as-if rule.
I have several inquiries as to the initialization issue (storage class issue may be related as well):
Global objects (defined without static keyword) are also static objects, right?
Yes, at file scope the static object is just about the visibility of the symbol. A global object can be referred to, by name, from another source file whilst a static object name is completely local to the current source file.
The confusion stems from the reuse of the world static in many different situations :(
Global objects are also initialized like static objects by two steps like above, right?
Yes, as are local static objects in fact.
What is the Static Initialization? Does it refer to initializing static objects (defined with static keyword)?
No, as explained above it refers to initializing objects without executing a user-defined function but instead copying a pre-computed byte pattern over the object's memory. Note that in the case of objects that will later be dynamically initialized, this is just zero-ing the memory.
I also read that objects defined within block (i.e. in a function) with static keyword is initialized when the execution thread first enters the block! This means that local static objects are not initialized before main function execution. This means they are not initialized as the two steps mentioned above, right?
They are initialized with the two steps process, though indeed only the first time execution pass through their definition. So the process is the same but the timing is subtly different.
In practice though, if their initialization is static (ie, the memory pattern is a compile-time pattern) and their address is not taken they might be optimized away.
Note that in case of dynamic initialization, if their initialization fails (an exception is thrown by the function supposed to initialize them) it will be re-attempted the next time flow-control passes through their definition.
Dynamic initialization refers to initialization of objects created by new operator, right? It might refer to initialization like myClass obj = myClass(100); or myClass obj = foo();
Not at all, it refers to initialization requiring the execution of a user defined function (note: std::string has a user-defined constructor as far as the C++ language is concerned).
EDIT: My thanks to Zach who pointed to me I erroneously called Static Initialization what the C++11 Standard calls Constant Initialization; this error should now be fixed.
I believe there are three different concepts: initializing the variable, the location of the variable in memory, the time the variable is initialized.
First: Initialization
When a variable is allocated in memory, typical processors leave the memory untouched, so the variable will have the same value that somebody else stored earlier. For security, some compilers add the extra code to initialize all variables they allocate to zero. I think this is what you mean by "Zero Initialization". It happens when you say:
int i; // not all compilers set this to zero
However if you say to the compiler:
int i = 10;
then the compiler instructs the processor to put 10 in the memory rather than leaving it with old values or setting it to zero. I think this is what you mean by "Static Initialization".
Finally, you could say this:
int i;
...
...
i = 11;
then the processor "zero initializes" (or leaves the old value) when executing int i; then when it reaches the line i = 11 it "dynamically initializes" the variable to 11 (which can happen very long after the first initialization.
Second: Location of the variable
There are: stack-based variables (sometimes called static variables), and memory-heap variables (sometimes called dynamic variables).
Variables can be created in the stack segment using this:
int i;
or the memory heap like this:
int *i = new int;
The difference is that the stack segment variable is lost after exiting the function call, while memory-heap variables are left until you say delete i;. You can read an Assembly-language book to understand the difference better.
Third: The time the variable is initialized
A stack-segment variable is "zero-initialized" or statically-initialized" when you enter the function call they are defined within.
A memory-heap variable is "zero-initialized" or statically-initialized" when it is first created by the new operator.
Final Remark
You can think about static int i; as a global variable with a scope limited to the function it is defined in. I think the confusion about static int i; comes because static hear mean another thing (it is not destroyed when you exit the routine, so it retains its value). I am not sure, but I think the trick used for static int i; is to put it in the stack of main() which means it is not destroyed until you exit the whole program (so it retains the first initialization), or it could be that it is stored in the data segment of the application.