Is the static initialization of global variables completed before `main()`? - c++

Some relevant excerpts from the C++ standard 1998:
The storage for objects with static storage duration shall be zero-initialized before any other initialization takes place. Zero-initialization and initialization with constant expression are collectively called static initialization; all other initialization is dynamic initialization. Objects of POD types with static storage duration initialized with constant expressions shall be initialized before any dynamic initialization takes place. Objects with static storage duration defined in namespace scope in the same translation unit and dynamically initialized shall be initialized in the order in which their definition appears in the translation unit.
It is implementation-defined whether or not the dynamic initialization 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.
Consider the following code.
int a = 1;
int main()
{
cout << a << endl;
return 0;
}
According to the standard, the static initialization takes place before the dynamic initialization, and the dynamic initialization may take place after main() is entered. My question is: is the global variable a initialized to be 1 before main() is entered? Then if all the threads are created after main() is entered the static initialization of global variables is guaranteed to be thread-safe.

The standard says that all objects are initialized in the same translation unit (aka object file which corresponds to a single source file) before any function is called in that translation unit. In your example, it looks like they are in the same file, so a will be initialized before main() is called.
The standard is allowing lazy initialization to occur in the event that a DLL is loaded at run time. If you allow run-time linkage of your code, you can't say that everything is initialized before main().

Yes, if you had a object outside a function such as
Foobar foo;
If Foobar has a constructor, it would nominally run before main(). Likewise its destructor runs after main() exits. I would be hesitant to make use of this feature though. One issue, if you have these sort of objects in multiple files the order of creation is indeterminate.

Related

Guarantee of deferred dynamic initialization of non odr-used global variable

Consider the following complete program consisting of two TU's:
// 1.cpp
bool init() { /* ... */ }
const auto _{init()};
// 2.cpp
int main() {}
Question: is there any guarantee that _ is initialized at some point (I do not care when)?
Now consider the program consisting of one TU:
// 1.cpp
bool init() { /* ... */ }
const auto _{init()};
int main() {}
Note that _ is not odr-used.
However, can main(), in the second case, be said to be odr-used, since it gets (sort of) "referred by the implementation" as it gets called when the program is run?
And if main() is odr-used, does this imply that _ is guaranteed to be initialized even if it's not odr-used?
EDIT:
This is what en.cppreference.com says about Deferred dynamic initialization:
If no variable or function is odr-used from a given translation unit,
the non-local variables defined in that translation unit may never be
initialized (this models the behavior of an on-demand dynamic library)
Can you answer my questions considering the above when reading my two examples?
It's supposedly the linker's job to collate all objects with static storage-duration from all translation units for initialization during program initiation - however, its a bit more than that, the guarantee is that those objects will be initialized before the use of any function within that translation unit.
basic.start.static/1: Variables with static storage duration are initialized as a
consequence of program initiation....
Also see:
basic.stc.static/2: If a variable with static storage duration has initialization or a
destructor with side effects, it shall not be eliminated even if it
appears to be unused...
The object _ is guaranteed to be initialized. According to [basic.start.static]/1,
Variables with static storage duration are initialized as a consequence of program initiation. Variables with
thread storage duration are initialized as a consequence of thread execution.
In case you were wondering whether that could be read only as guaranteeing that static initialization shall occur, and not guaranteeing that dynamic initialization shall occur, see [dcl.dcl]/11,
A definition causes the appropriate amount of storage to be
reserved and any appropriate initialization (11.6) to be done.
Thus, all initialization required by the semantics of the initializer {init()} shall be performed on the object _.
As usual, the as-if rule applies. If init() has any observable behaviour, such behaviour must occur. It has any side effects that affect observable behaviour, such side effects must occur.
The fact that _ is not odr-used is irrelevant. The tangent about main is irrelevant too.

Variable templates and std::cout -- order of construction

It looks like we can safely use std::cout object in constructors of objects with static storage duration as stated in this question.
However, I'm not entirely sure that we can safely use them in case of variable templates:
#include <iostream>
template<class T>
T x = T{};
void foo()
{
class Test
{
public:
Test() { std::cout << "Test::Test\n"; }
};
Test t = x<Test>;
}
int main()
{
std::cout << "main\n";
}
This code crashes in clang (live example) and I'm not sure whether it's a bug or not.
As explained in that question, one effect of
#include <iostream>
is the equivalent of defining a global variable
static std::ios_base::Init __init;
which (assuming that you include it at the start of the TU) guarantees that for all static storage duration objects with ordered initialization in the same TU, the stream objects have been set up.
However, explicitly and implicitly instantiated template specializations have unordered initialization ([basic.start.dynamic]/1)1:
Dynamic initialization of a non-local variable with static storage
duration is unordered if the variable is an implicitly or explicitly
instantiated specialization, and otherwise is ordered [note omitted]. Variables with ordered initialization defined within a single translation unit shall be initialized in the order of their definitions in the translation unit.
And since
If a program starts a thread, the subsequent unordered initialization
of a variable is unsequenced with respect to every other dynamic
initialization. Otherwise, the unordered initialization of a variable
is indeterminately sequenced with respect to every other dynamic
initialization.
there's no guarantee that the stream objects have been initialized at the time the variable template specialization x<Test> is initialized.
In this case, as one of the possible executions results in undefined behavior (using the stream objects before they are initialized), the behavior of the entire program is undefined (see [intro.execution]/5).
The fix is to construct a std::ios_base::Init object yourself in Test's constructor.
1 This is actually underspecified for variable templates when C++14 was published, but it's always been the intent.

Does the C++ standard require that dynamic initialization of static variables be performed in the main thread?

Does the C++ standard require that dynamic initialization of non-local static variables, be performed in the same thread that calls main()?
More specifically, in C++11, is std::this_thread::get_id() guaranteed to return the same result in static initializers and inside main()?
Edit:
Even more specifically, given the following code:
#include <iostream>
#include <thread>
static std::thread::id id = std::this_thread::get_id();
int main()
{
std::cout << id << "\n";
std::cout << std::this_thread::get_id() << "\n";
return 0;
}
are the two emitted thread IDs required/guaranteed to match?
No. The standard nowhere provides such a guarantee, and in fact the contrary is implied by [basic.start.init]/p2:
If a program starts a thread (30.3), the subsequent initialization of
a variable is unsequenced with respect to the initialization of a
variable defined in a different translation unit. Otherwise, the
initialization of a variable is indeterminately sequenced with respect
to the initialization of a variable defined in a different translation
unit. If a program starts a thread, the subsequent unordered
initialization of a variable is unsequenced with respect to every
other dynamic initialization. Otherwise, the unordered initialization
of a variable is indeterminately sequenced with respect to every other
dynamic initialization.
There would be no need to weaken the sequencing guarantee in the presence of threads if all initializations had to be performed on the same thread.
Standard doesn't say anything about what thread should perform such initialization. It only requires specific orderings and guarantees:
3.6.2 Initialization of non-local variables [basic.start.init]
2. Static initialization shall be performed before any dynamic initialization takes place. [...] Variables with ordered initialization defined within a single translation unit shall be initialized in the order of their definitions in the translation unit. [...] If a program starts a thread, the subsequent initialization of a variable is unsequenced with respect to the initialization of a variable defined in a different translation unit. Otherwise, the initialization of a variable is indeterminately sequenced with respect to the initialization of a variable defined in a different translation unit.
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 of any function or variable defined in the same translation unit as the variable to be initialized.
5. It is implementation-defined whether the dynamic initialization of a non-local variable with static or thread storage duration is done before the first statement of the initial function of the thread. If the initialization is deferred to some point in time after the first statement of the initial function of the thread, it shall occur before the first odr-use of any variable with thread storage duration defined in the same translation unit as the variable to be initialized.
However, most implementations will do so - initialization of static non-local variables will be performed in the same thread, that calls main(). Example from Visual C++ 11:
#include <iostream>
#include <thread>
using namespace std;
struct Cx
{
public:
Cx()
{
cout<<"Cx: "<<std::this_thread::get_id()<<endl;
}
};
static Cx c;
int main()
{
cout<<"Main: "<<std::this_thread::get_id()<<endl;
return 0;
}
Output:
Cx: 5820
Main: 5820
After setting breakpoint inside Cx::Cx():
No, though it may be a good idea to write your program that way. The syntax requires that static initialization happens in a deterministic way, but does not dictate things like the thread involved.

Destruction order of statically initialized, non-literal objects

A recent question drew my attention to the way that constexpr has changed in C++14. The new feature is that a non-local variable with static storage duration may be initialized in the static initialization phase if its initializer consists of a constexpr constructor, even if the type of the variable isn't a literal type. More precisely, the new wording in [basic.start.init] is:
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 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 [...]
The typical example is std::unique_ptr, which "should never be worse that hand-written":
std::unique_ptr<int> p; // statically initialized by [unique.ptr.single.ctor],
// requires no code excution
int main()
{
p = std::make_unique<int>(100);
}
// p is destroyed eventually
Prior to this addition, statically initialized variables were either of reference type or of literal object type, and therefore had trivial destructors. But now a statically initialized global variable can have a non-trivial destructor.
How is such a destructor call ordered with respect to the destructors of dynamically initialized global objects, with respect to other statically initialized ones, and how are the destructor calls sequenced?
Consider
If an object is initialized statically, the object is destroyed in the
same order as if the object was dynamically initialized.
and
If the completion of the constructor or dynamic initialization of an
object with static storage duration is sequenced before that of
another, the completion of the destructor of the second is sequenced
before the initiation of the destructor of the first.
Now,
Static initialization shall be performed before any dynamic
initialization takes place.
Clearly this answers the first question: Since p is guaranteed to be initialized before any dynamic initialization is performed, the destructor is called after any dynamically initialized object is destroyed.
Essentially the second question, i.e. what order the destructions of several statically initialized variables have, is reduced to the ordering of the initialization of these:
Dynamic initialization of a non-local variable with static storage
duration is either ordered or unordered. Definitions of explicitly
specialized class template static data members have ordered
initialization. Other class template static data members (i.e.,
implicitly or explicitly instantiated specializations) have unordered
initialization. Other non-local variables with static storage
duration have ordered initialization.
The bold sentence includes all statically initialized objects that are not static data members of instantiated classes. They are ordered within one translation unit:
Variables with ordered initialization defined within a single
translation unit shall be initialized in the order of their
definitions in the translation unit.
So, to summarize:
Variables which are subject of static initialization and are not static data members of an instantiated class are destroyed in the reverse order of definition in a translation file.
... those variables are always destroyed after any dynamically initialized object is destroyed.
However, despite possible argumentative mistakes, neither Clang nor GCC seem to implement it this way at the moment: Demo.
[basic.start.term]/1 (N4140) says:
If an object is initialized statically, the object is destroyed in the same order as if the object was dynamically initialized.
As I understand, this means that for the purpose of determinig the order of destruction, all static initialization is treated as dynamic (ordered or unordered) and the destructors are called in reverse order of this initialization.

Is the order of file-level static variables always the same within a given translation unit?

I have a program split up into two source files:
example.cpp
#include <iostream>
class A {
public:
A(int x) {
::std::cout << "In A(" << x << ")\n";
}
};
static A first(1);
static A second(2);
example__main.cpp
int main(int argc, const char *argv[])
{
return 0;
}
Is the output of this program guaranteed to be:
In A(1)
In A(2)
on all platforms and compilers? If so, where in the standard does it say this? Does it matter if I'm using namespaces and first and second appear in different namespaces? How about if they aren't static and I'm using an anonymous namespace?
Yes, the order of initialization is defined for non-local static objects if the declarations appear in the same translation unit.
From C++03,
(3.6/2) Objects with static storage duration defined in namespace scope in the
same translation unit and dynamically initialized shall be initialized
in the order in which their definition appears in the translation
unit. [Note: 8.5.1 describes the order in which aggregate members are
initialized. The initial-ization of local static objects is described
in 6.7. ]
Within one translation unit, global variables are initialized in several stages:
First, all variables that have "static initialization" are initialized in their order of declaration (see below).
Then, all "ordered dynamic initializations" are performed, again in their order of declaration.
There are also "unordered dynamic initializations", which are "unsequenced" with respect to the other dynamic initializations (but always after the static ones).
Destruction of statically and ordered-dynamically initialized globals proceeds in opposite order (and the unordered ones again "unsequenced", but before the static ones). The relative initialization ordering across TUs is unspecified.
To explain the terminology loosely: a global variable is "statically initialized" if it is either initialized to a constant (for constructor calls, this requires constexpr constructors), or if it is has no initializer and is declared static (which makes it zero-initialized): static int a; Foo b(1, true, Blue); On the other hand, if the initializer is not anything "constant", like a function call or a non-constexpr constructor, then the object is "dynamically initialized". Most ordinary globals that are dynamically initialized are "ordered"; the only "unordered" ones are static members of template specializations and such like.
(Note that all this got a lot more detailed in C++11, as there is now explicit attention to thread-local storage and initialization at the start of a thread.)