我已经看到很多关于此的问题,但没有一个包含有关如何编译此特定用例的代码的说明。我运行以下命令:g++ main.cpp c.cpp testobj.cpp -o main
,但运行此命令会给我一个Segmentation fault (core dumped)
。当我在main
中的main.cpp
方法中使用print语句并删除所有TestObj
代码时,它确实有效。
这是分配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";
}
testobj.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;
}
答案 0 :(得分:3)
这是由全局静态变量的初始化顺序引起的。它未定义,称为static initialization order fiasco。当TestObj::TestObj(
使用C::test
时,它尚未构建。
解决它的常用方法是将全局静态变量移动到函数局部静态变量中,即:
const std::string getTestString() {
static std::string test = "test";
return test;
}
现在,当你调用getTestString()
时,将构造测试变量,并且它将完成一次。此外,由于函数中的静态变量的C ++ 11初始化保证是线程安全的。
答案 1 :(得分:2)
虽然单个translation unit中全局变量的初始化顺序已明确定义,但翻译单元之间的顺序不是。
因此,如果testobj
源文件中的main.cpp
对象在C::test
对象之前初始化,那么您确实会有奇怪的行为。
如果您有多个翻译单元,每个单元都有全局变量,那么您就不能依赖它们之间的初始化顺序。