静态字符串初始化顺序问题

Static string initialization order issue

我在头文件中有 extern const 字符串声明,它在源文件中有定义:

// a.h
extern const std::string base;

// a.cpp
const std::string base = "base";

然后我在另一个头文件中还有一个extern const字符串,这个字符串的定义使用了第一个字符串的定义:

// b.h
extern const std::string usage;

// b.cpp
const std::string usage = base + " str";

在应用程序启动时出现此错误:

A dynamic link library (DLL) initialization routine failed.

我将调试器附加到应用程序,抛出以下异常:

Exception thrown: read access violation. this was nullptr.

这是在 b.cpp 中的 base 处抛出的。所以我认为这是静态初始化顺序的问题。但是在我的生成文件中,我在 b.obj 之前列出了 a.obj,所以我不明白为什么会这样。

请注意,我仅在 Windows 时收到此错误。 Linux 没问题。

一种补救方法是在头文件中定义base

// a.h
const std::string base = "base";

// a.cpp

这是唯一的解决办法吗?或者有更好的方法吗?

不确定为什么标题提到了静态字符串初始化,并且这种行为可能取决于所使用的编译器,但是对于 vs2017,您应该在 b.cpp 文件中包含 a.h header。它对我有用。谢谢。

您可以使用 #pragma init_seg

控制初始化顺序

指向 c++ 的指针默认位于 .CRT$XCU 部分(介于 .CRT$XCA__xc_a__xc_z 之间=17=] )

所以解决方案可以是下一个

// a.cpp
#pragma warning(disable : 4075)
#pragma init_seg(".CRT$XCU1")

const std::string base = "base";

// b.cpp
#pragma warning(disable : 4075)
#pragma init_seg(".CRT$XCU2")

const std::string usage = base + " str";

所以把 base 放到 ".CRT$XCU1"usage".CRT$XCU2" 这保证 base 将在 usage[=25 之前初始化=]