Статический порядок инициализации фиаско, iostream и C ++ 11

Согласно спецификации 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. Согласно спецификации, этого должно быть достаточно.

4

Решение

Полная цитата параграфа включает в себя:

Объекты строятся и ассоциации создаются в какое-то время до или во время первого
время создания объекта класса ios_base :: Init, и в любом случае до начала тела main
выполнение. 293)

И со сноской

293) Если они могут это сделать, реализациям рекомендуется инициализировать объекты раньше, чем требуется.

Таким образом, гарантия, что iostreams будет работать самое позднее при входе в основной. Не существует строгого требования, чтобы они работали раньше, если блок перевода не включает <iostream>,

Вы нашли способ обойти это!

При звонке foo() из B.cpp, ios_base::Init экземпляр, включенный в A.cpp, может или не может быть инициализирован.

6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]