When are inline variables in static storage initialized?
Asked Answered
F

1

6

C++ standards (earlier than C++17, at least) have said this about initialization order.

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.

C++17 introduces inline variables, which I believe to mean that a single variable with static storage duration and namespace scope and dynamic initialization could be defined in multiple translation units.

Does C++ make any guarantees about the initialization order of these variables?

Fairhaired answered 9/8, 2019 at 21:52 Comment(0)
S
5

See [basic.start.dynamic] p1:

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.

Therefore, the type of variable you are describing has "partially-ordered initialization". According to p2:

Dynamic initialization of non-local variables V and W with static storage duration are ordered as follows:

  • ...
  • 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.
  • ...

So to summarize, assuming that there are no instantiated templates in the picture:

  • If you have two namespace-scope inline variables V and W such that V is defined before W in every translation unit, then V is initialized before W.
  • If only V is inline, and W is some non-inline namespace-scope variable defined in exactly one translation unit, V will be initialized before W as long as V's definition precedes W's in that one translation unit.
  • If the non-inline variable is defined before the inline variable, their initialization order cannot be guaranteed.

An intuitive way to think about initialization order is that, just as in C++14, the compiler initializes each translation unit in order, with the relative ordering of different translation units unspecified (and they can be interleaved with each other), but an inline variable with external linkage is considered to be initialized the first time the implementation "hits" one of its definitions which may be in any translation unit.

Also see p5:

It is implementation-defined whether the dynamic initialization of a non-local inline variable with static storage duration is sequenced before the first statement of main or is deferred. If it is deferred, it strongly happens before any non-initialization odr-use of that variable. It is implementation-defined in which threads and at which points in the program such deferred dynamic initialization occurs.

Storfer answered 9/8, 2019 at 22:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.