8

If I have some variables that I'm initializing statically (before main begins), am I free to use any built-in stuff in these constructors, like <iostream> or <vector>?

The "static initialization order fiasco" occurs because the order in which static variables are initialized (among different translation units) is undefined.

So what if something benign like

std::cout << "Hello" << std::endl;

happens to rely on some static variable inside <iostream> being initialized ahead of time? (I'm not saying it does, but assume it did.) What's to say that these static variables inside built-in libraries are initialized before my own static variables? Like inside say "Person.cpp" or whatever.

Edit: Is std::cout guaranteed to be initialized? was suggested as a duplicate to this question. However, I think my question is slightly broader in scope because it asks about any standard built-in library, rather than just <iostream>.

Community
  • 1
  • 1
Joe
  • 81
  • 2
  • Possible duplicate of [Is std::cout guaranteed to be initialized?](http://stackoverflow.com/questions/8784892/is-stdcout-guaranteed-to-be-initialized) – user657267 Apr 12 '16 at 03:42
  • I suspect you'll have to make that decision per object. My guess is that any object that is in a standard library is initialized before dynamic initialization begins but that's only a guess. – R Sahu Apr 12 '16 at 04:02
  • Why do you think that `vector` has anything static to be initialised? – underscore_d Apr 12 '16 at 08:48
  • @underscore_d I never said it does. It probably doesn't. But I don't know that for sure. (whether it be for `vector` or any other standard library) Which is why I'm asking this question. – Joe Apr 13 '16 at 02:39

2 Answers2

1

The C++ standards make no strong statements of the behavior of the program before the start of main, or after main has completed.

In experience, I have found a number of issues where the C++ runtime has destroyed some object (e.g. resources used for management of std::mutex), which have created a deadlock in the destruction of a complex type.

I would recommend the following pattern for static's

C++ creates objects declared static in a function in the order they are executed. This leaves a pattern which will ensure that objects exist as they are needed.

   AnObject * AnObject::getInstance() {
       static AnObject a;
       return &a;
   }

This should be executed to get hold of the global, and will occur at the point when getInstance() is called.

C++ 11 onwards

This code is guaranteed to be thread-safe, where if multiple threads of execution arrive in getInstance, only one will construct the object and the rest will wait.

Pre C++ 11

Creating this pattern replaces ill-defined order with thread safety issues.

Luckily, it will be possible to create a criticalsection/mutex primative in main, which is able to arbitrate.

In some OSs (e.g. InitializeCriticalSection and Windows), these locks can safely be created before main as static variables.

   AnObject * AnObject::getInstance() {
       EnterCriticalSection( &aObjectcrit );
       static AnObject a;
       LeaveCriticalSection( &aObjectcrit );
       return &a;
   }

Assuming you have initialized aObjectcrit either in or before this function is called.

The result of this pattern is a form of onion construction, where objects are required in the order they are needed, and when the program exits, they are destroyed in the reverse order they were created in.

mksteve
  • 12,614
  • 3
  • 28
  • 50
-1

You're confusing objects (std::cout) and types (std::vector). The former is covered by the linked question, and the latter is a type. Static initialization applies to objects, but not to types.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 1
    I'm not confusing objects and types. It seems very unlikely, but what if `` relied, internally, on some static object being initialized before any `vector` is constructed? Or similar issues for any other standard library. – Joe Apr 13 '16 at 02:48
  • @Joe: That would be a bug in the implementation. Remember, the static initialization problem exists because there's no standard way to solve it across implementations, but the standard library is part of the implementation. It can use non-portable methods, so even if a particular implementation relied on such a static object, it would need to ensure it's properly initialized. – MSalters Apr 13 '16 at 06:43