11

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.

Community
  • 1
  • 1
spockwang
  • 897
  • 1
  • 6
  • 15
  • 1
    Does this anwer: http://stackoverflow.com/a/6373620/1491895 answer your question? – Barmar Jul 29 '14 at 03:18
  • 1
    yes, yes and yes. That is why C++ singleton pattern uses just a simple static variable sometimes: it is guarentteed to be initialized first – SwiftMango Jul 29 '14 at 03:25
  • @Barmar The answer just says the dynamic initialization takes place before its first use, not definitely before `main()`. – spockwang Jul 29 '14 at 03:50
  • What difference does it make? How can you tell the difference as long as it's initialized before you use it? – Barmar Jul 29 '14 at 03:59
  • I think that entering `main()` would count as use of a function in the same TU as `main`. Although there is no dynamic initialization in this code sample. – M.M Jul 29 '14 at 05:22
  • I don't see any text that says static initialization of `a` must complete before `a` is used, if the program has no dynamically-initialized objects. "If the initialization is deferred..." is only talking about dynamic initialization – M.M Jul 29 '14 at 05:32
  • 2
    Isn't `cout` dynamically initialised? Perhaps it would be better to modify your test program to simply `return a - 1;`, to be completely sure no objects are used that may or may not have dynamic initialisation. –  Jul 29 '14 at 05:44
  • @hvd Good point. Another question would be whether initialization of objects defined by the standard have static or dynamic initialization; we don't know what arguments are passed to the constructor of `cout`. Wouldn't it be hilarious if it turned out that `int a=1; int main() { return a/a-1; }` could invoke undefined behaviour according to the letter of the law – M.M Jul 29 '14 at 05:51
  • 1
    @Barmar The point is: Then if all the threads are created after main() is entered the static initialization of global variables is guaranteed to be thread-safe. – spockwang Jul 29 '14 at 06:16
  • @MattMcNabb: It can't, object initialization must occur before first use of `main` there. See §3.6.2, ISO/IEC 14882-2003. – Michael Foukarakis Jul 29 '14 at 06:42
  • @MichaelFoukarakis C++11 supersedes that standard – M.M Jul 29 '14 at 07:26
  • The numbering and wording remains exactly the same in ISO/IEC 14882:2011. – Michael Foukarakis Jul 29 '14 at 07:59

2 Answers2

6

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().

Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
  • While it is an interpretation, you do bring a good point with DLLs. I am not sure, however, than the interactions of loading/unloading DLLs are fully taken into account into the Standard; for example, I wonder if the wording on destruction of static variables is as careful. – Matthieu M. Jul 29 '14 at 08:39
  • @Matthieu M. The destruction is not "as careful". The standard knows nothing about DLLs, and those cannot in general provide the semantics that the standard mandates. On the other hand, this rule allows an implementation to strip static objects from TUs that are not used. – K-ballo Sep 15 '14 at 02:53
0

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.

seand
  • 5,168
  • 1
  • 24
  • 37
  • But the standard does not stat explicitly that the static initialization takes place before `main()`, let alone your dynamic initialization by the constructor. – spockwang Jul 29 '14 at 03:48
  • It's been a while since I've worked on this, but I know at least in Windows objects in file scope do get ctor-ed outside main(). _WinMainCRTStartup explicitly calls those and then main(). – seand Jul 30 '14 at 03:56