Согласно спецификации C ++ 11:
Результаты в том числе
<iostream>
в переводческом блоке должно быть как<iostream>
определил экземплярios_base::Init
со статической продолжительностью хранения. Точно так же вся программа должна вести себя так, как если бы
один экземплярios_base::Init
со статической продолжительностью хранения
Это означает, что если мой код выглядит так:
// A.cpp
#include <iostream>
using namespace std;
unsigned long foo() {
cerr << "bar";
return 42;
}
а также
// B.cpp
using namespace std;
extern unsigned long foo();
namespace {
unsigned long test() {
int id = foo();
return id;
}
unsigned long id = test();
}int main() {
return 0;
}
тогда я должен быть в безопасности звонить cerr
без риска статического фиаско инициализации.
К сожалению, этот код segfaults … Почему? Я не думаю, что gcc 6.2.1 решил игнорировать спецификацию C ++ 11, и я включил <iostream>
в A.cpp. Согласно спецификации, этого должно быть достаточно.
Полная цитата параграфа включает в себя:
Объекты строятся и ассоциации создаются в какое-то время до или во время первого
время создания объекта класса ios_base :: Init, и в любом случае до начала тела main
выполнение. 293)
И со сноской
293) Если они могут это сделать, реализациям рекомендуется инициализировать объекты раньше, чем требуется.
Таким образом, гарантия, что iostreams будет работать самое позднее при входе в основной. Не существует строгого требования, чтобы они работали раньше, если блок перевода не включает <iostream>
,
Вы нашли способ обойти это!
При звонке foo()
из B.cpp, ios_base::Init
экземпляр, включенный в A.cpp, может или не может быть инициализирован.
Других решений пока нет …