Страницы

Поиск по вопросам

вторник, 10 декабря 2019 г.

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

#cpp #терминология


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


Ответы

Ответ 1



Это фейл, который случается, когда переменные с динамической инициализацией используют для своей инициализации другие переменные с динамической инициализацией. В этом примере глобальная переменная g_b использует для инициализации значение глобальной переменной g_f из другой единицы трасляции, которая может быть, а может и не быть инициализирована к этому моменту, так как порядок динамической инициализации переменных в разных единицах трансляции не определен. На практике может получаться, что код с такой проблемой то работает, а то нет, в зависимости от особенностей компилятора, порядка сборки / линковки. // Foo.hpp #include struct foo{ ::std::string value; }; foo & Get_GlobalFoo(void); // Foo.cpp #include "foo.hpp" #include static foo g_f{::std::string{"whatever"}}; foo & Get_GlobalFoo(void) { return g_f; } // Bar.hpp #include 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 int main() { ::std::cout << Get_GlobalBar().value << ::std::endl; return 0; } Защититься от такой проблемы достаточно просто - достаточно никогда не прибегать к динамической инициализации (и заодно и к последующему разрушению). Проще говоря, все статические переменные должны быть constexpr и / или тривиально инициализироваться нулями, а также иметь тривиальный деструктор.

Ответ 2



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

Комментариев нет:

Отправить комментарий