Static variables initialisation order


Question

C++ guarantees that variables in a compilation unit (.cpp file) are initialised in order of declaration. For number of compilation units this rule works for each one separately (I mean static variables outside of classes).

But, the order of initialization of variables, is undefined across different compilation units.

Where can I see some explanations about this order for gcc and MSVC (I know that relying on that is a very bad idea - it is just to understand the problems that we may have with legacy code when moving to new GCC major and different OS)?

1
58
8/4/2014 5:42:35 PM

Accepted Answer

As you say the order is undefined across different compilation units.

Within the same compilation unit the order is well defined: The same order as definition.

This is because this is not resolved at the language level but at the linker level. So you really need to check out the linker documentation. Though I really doubt this will help in any useful way.

For gcc: Check out ld

I have found that even changing the order of objects files being linked can change the initialization order. So it is not just your linker that you need to worry about, but how the linker is invoked by your build system. Even try to solve the problem is practically a non starter.

This is generally only a problem when initializing globals that reference each other during their own initialization (so only affects objects with constructors).

There are techniques to get around the problem.

  • Lazy initialization.
  • Schwarz Counter
  • Put all complex global variables inside the same compilation unit.

  • Note 1: globals:
    Used loosely to refer to static storage duration variables that are potentially initialized before main().
  • Note 2: Potentially
    In the general case we expect static storage duration variables to be initialized before main, but the compiler is allowed to defer initialization in some situations (the rules are complex see standard for details).
69
4/2/2019 6:14:04 PM

I expect the constructor order between modules is mainly a function of what order you pass the objects to the linker.

However, GCC does let you use init_priority to explicitly specify the ordering for global ctors:

class Thingy
{
public:
    Thingy(char*p) {printf(p);}
};

Thingy a("A");
Thingy b("B");
Thingy c("C");

outputs 'ABC' as you'd expect, but

Thingy a __attribute__((init_priority(300))) ("A");
Thingy b __attribute__((init_priority(200))) ("B");
Thingy c __attribute__((init_priority(400))) ("C");

outputs 'BAC'.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon