Что такое “static initialization order fiasco” (SIOF)?

158
18 мая 2019, 06:50

Что такое "static initialization order fiasco" (SIOF)?

Answer 1

Это фейл, который случается, когда переменные с динамической инициализацией используют для своей инициализации другие переменные с динамической инициализацией. В этом примере глобальная переменная g_b использует для инициализации значение глобальной переменной g_f из другой единицы трасляции, которая может быть, а может и не быть инициализирована к этому моменту, так как порядок динамической инициализации переменных в разных единицах трансляции не определен. На практике может получаться, что код с такой проблемой то работает, а то нет, в зависимости от особенностей компилятора, порядка сборки / линковки.

// Foo.hpp
#include <string>
struct foo{ ::std::string value; };
foo & Get_GlobalFoo(void);
// Foo.cpp
#include "foo.hpp"
#include <string>
static foo g_f{::std::string{"whatever"}};
foo & Get_GlobalFoo(void) { return g_f; }
// Bar.hpp
#include <string>
struct bar{ ::std::string value; };
bar & Get_GlobalBar(void);
// Bar.cpp
#include "foo.hpp"
#include "bar.hpp"
static bar g_b{Get_GlobalFoo().value};
bar & Get_GlobalBar(void) { return g_b; }
// Main.cpp
#include "bar.hpp"
#include <iostream>
int main()
{
    ::std::cout << Get_GlobalBar().value << ::std::endl;
    return 0;
}

Защититься от такой проблемы достаточно просто - достаточно никогда не прибегать к динамической инициализации (и заодно и к последующему разрушению). Проще говоря, все статические переменные должны быть constexpr и / или тривиально инициализироваться нулями, а также иметь тривиальный деструктор.

Answer 2

Несмотря на страшное название, вещь это очень простая. Представим, что у нас есть две статических переменных в разных исходных файлах, причем одна из них при инициализации каким-то образом ссылается на другую, например, вызывает метод класса. Поскольку порядок инициализации статических переменных не определен, существует 50%-ая вероятность, что зависимая переменная будет инициализирована первой, и при этом обратится к еще неинициализированной второй переменной. Программа соответственно аварийно завершится, не выполнив ни единого оператора. Вот эта ситуация и называется SIOF.

Поэтому классовые переменные лучше вообще не делать статическими, или хотя бы следить, чтобы таких зависимостей не возникало.

READ ALSO
Массив заполняется не полностью c++

Массив заполняется не полностью c++

Нужно нарисовать пирамиду, содержащую n строкЕсли n будет, например, 4, то пирамида должна выглядеть следующим образом:

125
Список ip, подключенных к localhost SFML C++

Список ip, подключенных к localhost SFML C++

Хочу спросить, как получить список игроков их ip, на localhost и как отслеживать их подключение

114
Реализация template в .cpp-файле [дубликат]

Реализация template в .cpp-файле [дубликат]

На данный вопрос уже ответили:

142