Здравствуйте, HolyNick, Вы писали:
HN>Здравствуйте, Посторонним В., Вы писали:
ПВ>>Есть такой код
ПВ>>a.h
ПВ>>ПВ>>...
ПВ>>namespace X
ПВ>>{
ПВ>> const std::string Foo = "foo";
ПВ>> inline std::string getFoo()
ПВ>> {
ПВ>> return Foo;
ПВ>> }
ПВ>>}
ПВ>>...
ПВ>>
ПВ>>a.cpp:
ПВ>>ПВ>>#include "a.h"
ПВ>>...
ПВ>>namespace X
ПВ>>{
ПВ>> const string Default_Foo = getFoo();
ПВ>>}
ПВ>>...
ПВ>>
ПВ>>Само-собой в проекте есть еще файлы, который инклудят a.h
ПВ>>На старте программа валится в segfault в выделенной строчке. Исследование показало, что:
ПВ>>1. в программе создается несколько копий Foo
ПВ>>ПВ>>-bash-4.2# nm -oC a.out | grep Foo
ПВ>>/usr/local/bin/RESEPT/www/authmod.fcgi:3c162c50 b X::Foo
ПВ>>/usr/local/bin/RESEPT/www/authmod.fcgi:3c162990 b X::Foo
ПВ>>/usr/local/bin/RESEPT/www/authmod.fcgi:3c1641b0 b X::Foo
ПВ>>
ПВ>>2. В процессе инициализации Default_Foo вызывается getFoo(), которая берет не уже инициализированую Foo из единицы компиляции a.cpp (как я бы ожидал), а Foo из другой единицы компиляции, в которой, волею судеб, Foo еще не инициализирована.
ПВ>>Что приводит в segfault-у.
ПВ>>Кто-нибудь может объяснить, верно ли такое поведение?
ПВ>>Как лучше всего избегать такого рода ошибок?
HN>Глобальные\статические переменные определенные в одной единице трансляции скорее всего будут создаваться\инициализироваться в порядке их определения. Порядок инициализации
HN>глобальных\статических переменных в разных единицах трансляции определяется порядком их(сpp файлов) обработки линковщиком, те для программиста заранее неизвестен в общем-то.
HN>Лучше избегать связи между глобальными переменными, да и их самих желательно иметь поменьше.
HN>HN>//в cpp файле, а не h
HN>std::string getDefaultFoo()
HN>{
HN> static const std::string Foo = "foo";
HN> return Foo;
HN>}
HN>
PS: Обработка линковщиком конечно же объектных файлов.