Solve SIOF (Static Initialization Order Fiasco) with Meyer's Singleton.

Xiahua Liu January 14, 2025 #Linux

What is SIOF?

The Static Initialization Order Fiasco (SIOF) is a common C++ issue that occurs when initialization order of static objects across different translation units is undefined. As explained in the C++ standard:

The static initialization order fiasco refers to the ambiguity in the order that objects with static storage duration in different translation units are initialized in.

A Simple SIOF Example

// filepath: a.cpp
class A {
public:
    A() { value = 42; }
    int value;
};

static A globalA;  // Static object in first translation unit
// filepath: b.cpp
#include <iostream>
extern A globalA;  // Reference to static object from a.cpp

class B {
public:
    B() { 
        // May crash - globalA might not be initialized yet!
        std::cout << "A's value: " << globalA.value << std::endl;
    }
};

static B globalB;  // Problem: Order of initialization is undefined

Understanding Initialization Stages

There are two key stages in initializing non-local objects:

1. Static Initialization

2. Dynamic Initialization

Occurs in two possible ways:

The Solution: Deferred Initialization

To avoid SIOF, we should use deferred initialization for all the non-const static variables. Here's a practical example:

// filepath: a.cpp
class A {
public:
    A() { value = 42; }
    int value;
    
    static A& getInstance() {
        static A instance;  // Safe: initialized on first use
        return instance;
    }
};
// filepath: b.cpp
class B {
public:
    B() {
        // Safe: A is guaranteed to be initialized before use
        std::cout << "A's value: " << A::getInstance().value << std::endl;
    }
    
    static B& getInstance() {
        static B instance;  // Also using function-local static
        return instance;
    }
};

It is called Meyer's Singleton.