我在命名空间中初始化一些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
都被分配了字符串文字。执行继续到initialziae HI_AND_BYE
,但是当我们进入createHiAndByeVector()
函数时,HI
和BYE
都不再有值。然后我在push_back()
方法中得到了分段错误。如果我查看调用堆栈,我会看到以下行:__static_initialization_and_destruction_0()
。到底是怎么回事?我的物体在施工后会立即被毁坏吗?
答案 0 :(得分:1)
我的猜测是这里的问题违反了One Definition Rule(ODR)。这里的猜测是这个代码实际上是在一个标题中,这也是你将函数声明为内联的原因。
现在,此代码以多个翻译单元(.cpp文件),TU1和TU2编译。这导致两组常量和内联函数。现在,当链接时,常量彼此独立存在,因为它们具有内部链接(命名空间级别的const导致这种情况)。但是,该函数没有内部链接,而是指示链接器通过inline
丢弃除一个实例之外的所有实例。现在,剩下的一个用于初始化TU1和TU2中的向量,但它使用其中一个的常量字符串。根据初始化的时间(未定义),它可以工作与否。这基本上是Deamonpog上面提到的初始化顺序惨败。
回到ODR,问题是内联函数被编译两次但它们不相同,因为它们隐式引用不同的字符串常量。如果在标头中有匿名名称空间,则会出现类似问题。顺便说一句:除此之外,这个问题与名称空间无关!有两种方法可以解决这个问题:
extern string const BYE;
)常量,并在单独的TU中实现它们(string const BYE = "Bye!";
)。这样,您只有一个可以由程序的不同部分共享的实例。答案 1 :(得分:-1)
我认为这是由于初始化Fiasco。以下链接可以帮助您。问题是全局/静态变量是以随机方式初始化的。没有特定的初始化顺序。所以也许你的HI_AND_BYE在HI或BYE初始化之前被初始化。!!!
Finding C++ static initialization order problems
http://www.parashift.com/c++-faq-lite/static-init-order.html