2016-04-14 438 views
0

我已经看到很多关于此的问题,但没有包含关于如何编译这个特定用例的代码的解释。我运行以下命令:g++ main.cpp c.cpp testobj.cpp -o main,但运行这给我一个Segmentation fault (core dumped)。当我在main.cppmain方法中有打印语句并删除所有TestObj代码时,它确实起作用。命名空间中的C++全局变量

这是分配C::test常量的正确方法吗?

main.cpp中:

#include "c.h" 
#include "testobj.h" 

TestObj testobj; 

int main() { 
    return 0; 
} 

c.h:

#ifndef CONSTANTS 
#define CONSTANTS 

#include <string> 

namespace C { 
    extern std::string test; 
} 
#endif 

c.cpp:

#include "c.h" 

namespace C { 
    std::string test = "test"; 
} 

测试obj.h:

#ifndef TESTOBJ 
#define TESTOBJ 

class TestObj { 
public: 
    TestObj(); 
}; 

#endif 

testobj.cpp:

#include "testobj.h" 
#include <iostream> 
#include "c.h" 

TestObj::TestObj() { 
    std::cout << C::test << std::endl; 
} 

回答

2

虽然初始化一个translation unit中的全局变量的顺序被很好地定义,翻译单元之间的顺序是

所以如果main.cpp源文件中的testobj对象在C::test对象之前被初始化,那么你的确会有奇怪的行为。

如果你有多个翻译单元,每个翻译单元都有全局变量,那么你不能依赖它们之间的初始化顺序。

+0

我保存将'TestObj testobj'的声明更改为'TestObj * testobj',并通过执行'* testobj = TestObj()'将初始化移动到'main()'方法。 – martijnn2008

+0

@ martijnn2008是的,如果你考虑使用指针安全。 :)所有全局变量初始化后,总是会调用main函数。 –

1

这是由全局静态变量的初始化顺序造成的。它是未定义的,被称为static initialization order fiasco。当TestObj::TestObj(使用C::test - 它尚未构建。

解决这个问题的常用方法是全局静态变量移动到一个函数局部静态变量,即:

const std::string getTestString() { 
    static std::string test = "test"; 
    return test; 
} 

现在,当你调用getTestString()测试变量将被构建,它会做恰好一次。另外,由于C++ 11中函数中静态变量的初始化保证是线程安全的。

+0

此外,在静态变量的构造函数中使用std :: cout是不安全的,因为std :: cout本身是静态变量,我们也依赖于它的初始化。 –

+0

@IgorSemenov我没想过,因为C++ 11它看起来像是修复了 - http://stackoverflow.com/questions/8784892/is-stdcout-guaranteed-to-be-initialized – marcinj