Инициализация объектов const в пространстве имен

У меня проблема с инициализацией некоторых константных объектов в моем пространстве имен. У меня есть пространство имен, подобное следующему:

namespace myNamespace{
const std::string HI = "Hi";
const std::string BYE = "Bye";

inline std::vector<std::string> createHiAndByeVector(){
std::vector<std::string> temp;
temp.push_back(HI);
temp.push_back(BYE);
return temp;
}

const std::vector<std::string> HI_AND_BYE = createHiAndByeVector();
}

Если я отлаживаю инициализацию, я вижу, что оба HI а также BYE получить назначенные строковые литералы. Казнь продолжается до инициализации HI_AND_BYE, но когда мы попадаем в createHiAndByeVector() функция, оба HI а также BYE больше не имеет значений. Затем я получаю ошибку сегментации в push_back() метод. Если я смотрю на стек вызовов, я вижу строку: __static_initialization_and_destruction_0(), Что здесь происходит? Мои объекты разрушаются сразу после их постройки?

2

Решение

Я предполагаю, что проблема здесь в нарушении правила единого определения (ODR). Предполагается, что этот код фактически находится в заголовке, что также является причиной того, что вы объявили функцию как встроенную.

Теперь этот код скомпилирован в несколько блоков перевода (файлы .cpp), TU1 и TU2. Это приводит к двум наборам как констант, так и встроенной функции. Теперь при связывании константы существуют независимо друг от друга, потому что они имеют внутреннюю связь (это вызывает const на уровне пространства имен). Тем не менее, функция не имеет внутренней связи, а компоновщик проинструктирован отказаться от всех экземпляров, кроме одного через inline, Теперь оставшийся используется для инициализации векторов как в TU1, так и в TU2, но он использует строки констант из одного из них. В зависимости от того, когда они инициализируются, что не определено, оно может работать или нет. Это в основном фиаско порядка инициализации, о котором упоминает Deamonpog выше.

Возвращаясь к ODR, проблема в том, что встроенная функция компилируется дважды, но они не совпадают, потому что они неявно ссылаются на разные строковые константы. Подобные проблемы возникают, когда у вас есть анонимные пространства имен в заголовках. Кстати: кроме этого, эта проблема не имеет ничего общего с пространствами имен! Есть два способа решить эту проблему:

  1. Сделайте функцию init тоже статичной. Это отделяет все эти константы и функцию от их братьев в других единицах перевода.
  2. Вы только заявляете (extern string const BYE;) константы в заголовке и их реализация (string const BYE = "Bye!";) в отдельном ТУ. Таким образом, у вас есть только один их экземпляр, который может использоваться разными частями вашей программы.
1

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

Я думаю, что это связано с инициализацией Fiasco. Следующие ссылки могут помочь вам. Проблема в том, что глобальные / статические переменные инициализируются случайным образом. Нет определенного порядка их инициализации. Поэтому, возможно, ваш HI_AND_BYE инициализируется до инициализации HI или BYE. !!!

Нахождение C ++ статических проблем порядка инициализации

http://www.parashift.com/c++-faq-lite/static-init-order.html

-1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector