Do objects of built-in types have special static initialisation order precedence?

此生再无相见时 提交于 2019-12-04 03:22:56

问题


I'd have expected the following code to yield a segmentation fault (or otherwise UB):

struct T {
   T();
};

T t;
char const* str = "Test string";

T::T() {
   std::cout << str; // zero-initialised, only!
}

int main() {}

That's because t is initialised before str. I'd expect str to hold the value (char const*)0 due to zero-initialisation. My interpretation of [C++11: 3.6.2/2] supports this.

However, the above snippet appears to output the string as expected (and I confirmed the behaviour by also printing the pointer's value).

Is there some rule of static initialisation that I'm missing here, that allows str to be value-initialised before t begins construction? Where is it in the standard?


This came up on static variable resolution at build time, where an answerer asserted that using char const* rather than std::string for a static global avoids the static initialisation order fiasco. I disagreed, but now I'm not so sure...


回答1:


str is initialized by a constant expression and const char * is a POD type (C++03 terms, but C++11 it is analogous, but with different terms and way more allowed cases). Such an initialization is done in static initialization phase, and the static initialization phase has no issue of order. It happens before any dynamic initialization. t is initialized in the dynamic initialization phase.




回答2:


Built-in types aren't initialised at all, in the normal sense. Commonly, their initial contents are memory-mapped directly from a special region of the binary as part of loading it.




回答3:


I think I found it; what's happening here is not so much about the built-in type, but about the constant initialiser:

[C++11: 3.6.2/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. [..]

That final sentence would seem to override subsequent sequencing rules, making this ordering apply across Translation Units.




回答4:


char const* str = "Test string";

is done by the compiler/linker, so it exists in its "initialized state" before the program even starts to run.



来源:https://stackoverflow.com/questions/8750407/do-objects-of-built-in-types-have-special-static-initialisation-order-precedence

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!