Static variables initialisation order
As you say the order is undefined across different compilation units.
Within the same compilation unit the order is well defined: The same order as definition.
This is because this is not resolved at the language level but at the linker level. So you really need to check out the linker documentation. Though I really doubt this will help in any useful way.
For gcc: Check out ld
I have found that even changing the order of objects files being linked can change the initialization order. So it is not just your linker that you need to worry about, but how the linker is invoked by your build system. Even try to solve the problem is practically a non starter.
This is generally only a problem when initializing globals that reference each other during their own initialization (so only affects objects with constructors).
There are techniques to get around the problem.
- Lazy initialization.
- Schwarz Counter
- Put all complex global variables inside the same compilation unit.
- Note 1: globals:
Used loosely to refer to static storage duration variables that are potentially initialized beforemain()
. - Note 2: Potentially
In the general case we expect static storage duration variables to be initialized before main, but the compiler is allowed to defer initialization in some situations (the rules are complex see standard for details).
C++ static variables initialization order
The first scenario is well-defined in [basic.start.init]/2:
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.
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, if the constructor is a
constexpr
constructor, if all constructor arguments are constant expressions (including conversions), and if, after function invocation substitution (7.1.5), every constructor call and full-expression in the mem-initializers and in the brace-or-equal-initializers for non-static data members is a constant expression;- if an object with static or thread storage duration is not initialized by a constructor call and if every full-expression that appears in its initializer is a constant expression.
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. (...)
(Emphasis mine)
The upshot of this fairly lengthy paragraph is that
int n = 2;
is static initialization, while
int k = n;
is dynamic initialization (because n
is not a constant expression), and therefore n
is initialized before k
even if it appears later in the code.
The same logic applies in the case of the Base::static_constructor
example -- because the constructor of Base::static_constructor
is not constexpr
, Base::constructor
is dynamically initialized, whereas Base::i
is statically initialized. The initialization of Base::i
therefore takes place before the initialization of Base::constructor
.
On the other hand, the second case with
int n = func();
puts you squarely in the territory of unspecified behavior, and it is quite explicitly mentioned in [basic.start.init]/3:
An implementation is permitted to perform the initialization of a non-local variable with static storage duration as a static initialization even if such initialization is not required to be done statically, provided that
- the dynamic version of the initialization does not change the value of any other object of namespace scope prior to its initialization, and
- the static version of the initialization produces the same value in the initialized variable as would be produced by the dynamic initialization if all variables not required to be initialized statically were initialized dynamically.
[Note: As a consequence, if the initialization of an object
obj1
refers to an objectobj2
of namespace scope potentially requiring dynamic initialization and defined later in the same translation unit, it is unspecified whether the value ofobj2
used will be the value of the fully initializedobj2
(becauseobj2
was statically initialized) or will be the value ofobj2
merely zero-initialized. For example,inline double fd() { return 1.0; }
extern double d1;
double d2 = d1; // unspecified:
// may be statically initialized to 0.0 or
// dynamically initialized to 0.0 if d1 is
// dynamically initialized, or 1.0 otherwise
double d1 = fd(); // may be initialized statically or dynamically to 1.0
-- end note]
static global variables initialization order
6.6.3 Dynamic initialization of non-local variables [basic.start.dynamic]
- Dynamic initialization of a non-local
variable with static storage duration is unordered if the variable is
an implicitly or explicitly instantiated specialization, is
partially-ordered if the variable is an inline variable that is not an
implicitly or explicitly instantiated specialization, and otherwise is
ordered. [ Note: An explicitly specialized non-inline static data
member or variable template specialization has ordered initialization.
— end note ]- Dynamic initialization of non-local variables V and W
with static storage duration are ordered as follows:
- If V and
W have ordered initialization and V is defined before W within a
single translation unit, the initialization of V is sequenced before
the initialization of W.- If V
has partially-ordered initialization, W does not have unordered
initialization, and V is defined before W in every translation unit in
which W is defined, then
- if the program starts a thread
(4.7) other than the main thread (6.6.1), the initialization of V
strongly happens before the initialization of W;- otherwise,
the initialization of V is sequenced before the initialization of W.- Otherwise, if the program starts a thread other than the main
thread before either V or W is initialized, it is unspecified in which
threads the initializations of V and W occur; the initializations are
unsequenced if they occur in the same thread.- Otherwise, the
initializations of V and W are indeterminately sequenced.
Quoted from N4659, formatting adjusted to work with the markdown supported here.
For the exact definition of dynamic initialization, see the preceding subsesction 6.6.2 [basic.start.static].
Order of initialization of static variable in Java
It depends on when each class is first used.
From section 12.4.1 of the Java Language Specification:
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
T is a class and an instance of T is created.
T is a class and a static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
A reference to a static field (§8.3.1.1) causes initialization of only the class or interface that actually declares it, even though it might be referred to through the name of a subclass, a subinterface, or a class that implements an interface.
Section 12.4.2 of the JLS specifies the initialization procedure in detail.
To be honest, if your code requires one to be initialized before the other, despite having no obvious dependency, then you've got problems anyway.
What is the static variable initialization order across classes in C#?
It's fine for one type to depend on another type being initialized, so long as you don't end up in a cycle.
Basically this is fine:
public class Child
{
static Child() {} // Added static constructor for extra predictability
public static readonly int X = 10;
}
public class Parent
{
static Parent() {} // Added static constructor for extra predictability
public static readonly int Y = Child.X;
}
The result is well-defined. Child
's static variable initializers are executed prior to the first access to any static field in the class, as per section 10.5.5.1 of the spec.
This isn't though:
public class Child
{
public static readonly int Nasty = Parent.Y;
public static readonly int X = 10;
}
public class Parent
{
public static readonly int Y = Child.X;
}
In this latter case, you either end up with Child.Nasty=0
, Parent.Y=10
, Child.X=10
or Child.Nasty=0
, Parent.Y=0
, Child.X=10
depending on which class is accessed first.
Accessing Parent.Y first
will start initializing Parent
first, which triggers the initialization of Child
. The initialization of Child
will realise that Parent
needs to be initialized, but the CLR knows that it's already being initialized, so carries on regardless, leading to the first set of numbers - because Child.X
ends up being initialized before its value is used for Parent.Y
.
Accessing Child.Nasty
will start initializing Child
first, which will then start to initialize Parent
. The initialization of Parent
will realise that Child
needs to be initialized, but the CLR knows that it's already being initialized, so carries on regardless, leading to the second set of numbers.
Don't do this.
EDIT: Okay, more detailed explanation, as promised.
When is a type initialized?
If a type has a static constructor, it will only be initialized
when it's first used (either when a static member is referenced, or
when an instance is created). If it doesn't have a static
constructor, it can be initialized earlier. In theory, it could also
be initialized later; you could theoretically call a constructor or
a static method without the static variables being initialized - but
it must be initialized before static variables are referenced.
What happens during initialization?
First, all static variables receive their default values (0, null
etc).
Then the static variables of the type are initialized in textual
order. If the initializer expression for a static variable requires
another type to be initialized, then that other type will be
completely initialized before the variable's value is assigned -
unless that second type is already being initialized (due to a
cyclic dependency). Essentially, a type is either:
- Already initialized
- Being initialized at the moment
- Not initialized
Initialization is only triggered if the type is not initialized.
This means that when there are cyclic dependencies, it is possible
to observe a static variable's value before its initial value has
been assigned. That's what my Child
/Parent
example shows.
After all the static variable initializers have executed, the static
constructor executes.
See section 10.12 of the C# spec for more details on all of this.
By popular demand, here was my original answer when I thought the question was about the initialization order of static variables within a class:
Static variables are initialized in textual order, as per section 10.5.5.1 of the C# spec:
The static field variable initializers
of a class correspond to a sequence of
assignments that are executed in the
textual order in which they appear in
the class declaration.
Note that partial types make this trickier as there's no one canonical "textual order" of the class.
Static member initialization order within a single C# class
In short, don't do this.
Standard ECMA-334 C# Language Specification
15.5.6.2 Static field initialization
The static field variable initializers of a class correspond to a
sequence of assignments that are executed in the textual order in
which they appear in the class declaration (§15.5.6.1). Within a
partial class, the meaning of "textual order" is specified by
§15.5.6.1. If a static constructor (§15.12) exists in the class,
execution of the static field initializers occurs immediately prior to
executing that static constructor. Otherwise, the static field
initializers are executed at an implementation-dependent time prior to
the first use of a static field of that class
The fix is to :
- Put them in the order and use Static Constructor,
- or just Initialise them in a Static Constructor in turn giving you the ability to control the order of initialisation (given the above information).
Personally i suggest to Initialise them in a Static Constructor, it seems to make it more concrete and understandable, and less likely to be bumped in refactoring
C++ static initialization order: adding into a map
Being lazy, here's a copy from http://en.cppreference.com/:
Non-local variables
All non-local variables with static storage duration are initialized as part of program startup, before the execution of the main function begins (unless deferred, see below).
...
Dynamic initialization
After all static initialization is completed, dynamic initialization of non-local variables occurs in the following situations:
...
Deferred dynamic initialization
It is implementation-defined whether dynamic initialization happens-before the first statement of the main function (for statics) or the initial function of the thread (for thread-locals), or deferred to happen after.
If the initialization of a non-inline variable is deferred to happen after the first statement of main/thread function, it happens before the first odr-use of any variable with static/thread storage duration defined in the same translation unit as the variable to be initialized.
The important part is odr-use:
ODR-use
Informally, an object is odr-used if its value is read (unless it is a compile time constant) or written, its address is taken, or a reference is bound to it;
Since the s_map
is populated through Factory::Register
, I don't see a problem here.
If the map implementation is very trivial, it may even be initialized as part of the static initialization/at compile time.
But even if the initialization is deferred, it will be initialized before the use in Factory::Register
, as long as both are in the same translation unit.
However, if the map is defined in one translation unit, and Factory::Register
is defined in another, anything can happen.
Static function variable initialization order in the same function
Quoting from cppreference (emphasis mine):
Variables declared at block scope with the specifier
static
have static storage duration but are initialized the first time control passes through their declaration (unless their initialization is zero- or constant-initialization, which can be performed before the block is first entered). On all further calls, the declaration is skipped.
Since control flows top-to-bottom, the variables will indeed be initialized in declaration order.
Related Topics
Is #Pragma Once a Safe Include Guard
How to Serialize an Object in C++
How to Clear a Stringstream Variable
Is There a Difference Between Foo(Void) and Foo() in C++ or C
Unicode Encoding For String Literals in C++11
Static Initialization Order Fiasco
Linking Static Libraries to Other Static Libraries
Algorithm to Convert Rgb to Hsv and Hsv to Rgb in Range 0-255 For Both
Detecting Signed Overflow in C/C++
Performance of Built-In Types: Char VS Short VS Int Vs. Float Vs. Double
Using Custom Std::Set Comparator
Undefined Reference to Static Constexpr Char[]
Is the Sizeof(Some Pointer) Always Equal to Four
What Is an 'Undeclared Identifier' Error and How to Fix It
Good Input Validation Loop Using Cin - C++
How to Write Iso C++ Standard Conformant Custom New and Delete Operators
What Are the Errors, Misconceptions or Bad Pieces of Advice Given by Cplusplus.Com