🪤Go deeper — read the bookC++ Gotchas & Trick Questions— runnable code & full walkthrough →

cpp core · high

Static Initialization Order Fiasco

The static initialization order fiasco happens when a namespace-scope global in one translation unit depends, during its own construction, on a global defined in another translation unit. Within a single .cpp file globals are initialized top to bottom, but the order across files is unspecified and can change with link order, flags, or added files. When the dependent global is built first it reads an uninitialized object — undefined behavior. The standard fix is construct-on-first-use: move the object into a function as a static local and return a reference to it. It is then constructed the first time the function is called, guaranteeing the dependency is ready before use, and since C++11 that lazy initialization is also thread-safe ('magic statics').

🔑 Key line

The construction order of globals in different translation units is unspecified, so one global's constructor can read another before it is built (UB); fix it with construct-on-first-use — a function returning a static local, which is built lazily on first call and is thread-safe since C++11.

The code

// ---- config.cpp ----
struct Config {
int level = 42;
};
Config cfg; // namespace-scope global (dynamic init)
// ---- logger.cpp ---- (a different translation unit)
extern Config cfg;
Logger logger{cfg.level}; // reads cfg DURING its own construction
// FIX: construct-on-first-use
Config& config() {
static Config c;
return c;
} // lazy, thread-safe (C++11)
Logger logger{config().level}; // config() builds c on first call -> always ready

What this lesson walks through

  1. 01Two globals, two translation units
  2. 02Lucky order: it works... today
  3. 03Unlucky order: the fiasco fires
  4. 04Fix: construct-on-first-use
  5. 05First use triggers construction
  6. 06Bonus: it is thread-safe
  7. 07The rule in one breath

cfg lives in config.cpp; logger lives in logger.cpp and reads cfg while constructing. Within one file, globals init top-to-bottom — but the order across different .cpp files is unspecified.

See it animated — step by step, at your own pace

Unlock the full interactive walkthrough of Static Initialization Order Fiasco and 100+ animated C++ interview lessons.

← Previous
Endianness & Byte Order
Next →
Strict Aliasing & Type Punning