创建构造函数引用全局变量的类的全局实例时,c ++程序崩溃

bea*_*uxq 5 c++ global global-variables

我正在尝试创建一个类的全局实例,其构造函数引用一个全局变量.

该程序编译没有错误.但是当它运行时,它会在全局变量的引用上崩溃.

如何在没有构造函数崩溃的情况下创建此类的全局实例?

这是我制作的SSCCE:

/* main.cpp */
#include "TestClass.h"

// I need a global instance of TestClass
TestClass j;

int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

-

/* C.h */
#ifndef C_H_INCLUDED
#define C_H_INCLUDED

#include <string>

// global
extern const std::string S;

#endif // C_H_INCLUDED
Run Code Online (Sandbox Code Playgroud)

-

/* C.cpp */
#include "C.h"

#include <string>

// extern definition of global
const std::string S = "global string data";
Run Code Online (Sandbox Code Playgroud)

-

/* TestClass.h */
#ifndef TESTCLASS_H_INCLUDED
#define TESTCLASS_H_INCLUDED

class TestClass
{
public:
    TestClass();
};

#endif // TESTCLASS_H_INCLUDED
Run Code Online (Sandbox Code Playgroud)

-

/* TestClass.cpp */
#include "TestClass.h"

#include <iostream>

#include "C.h"  // for S global

TestClass::TestClass()
{
    std::cout << S << std::endl;  // this line crashes the program
}
Run Code Online (Sandbox Code Playgroud)

有关崩溃的调试器消息:

Program received signal SIGSEGV, Segmentation fault.
In std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) () ()
#1  0x004014f9 in TestClass::TestClass (this=0x4a0024 <j>) at E:\cpp\externconsttest\TestClass.cpp:9
E:\cpp\externconsttest\TestClass.cpp:9:117:beg:0x4014f9
At E:\cpp\externconsttest\TestClass.cpp:9
#1  0x004014f9 in TestClass::TestClass (this=0x4a0024 <j>) at E:\cpp\externconsttest\TestClass.cpp:9
E:\cpp\externconsttest\TestClass.cpp:9:117:beg:0x4014f9
Run Code Online (Sandbox Code Playgroud)

此示例在operator <<中崩溃,但无论引用的方式如何,它都会在对S的任何引用上崩溃.

sir*_*rge 5

我想,它崩溃,因为全球const std::string S尚未初始化的时候,当你的构造器中TestClass被调用。这是C ++中全局变量和静态变量的一个普遍问题:通常,您不知道全局变量和静态变量的初始化顺序(实际上,它们是按照在链接阶段将目标文件传递给链接器的顺序进行初始化的-但这就是不是很有帮助)。对于此问题有几种不同的解决方案。其中之一是:

  1. 创建一个在其主体中具有静态变量的函数,该函数返回对该变量的引用(而不是仅使用全局变量,您将调用该函数)。这类似于单例设计模式:

    const std::string& get_my_string() { static const std::string S; return S; }

然后在您的构造函数中:

TestClass::TestClass()
{
    std::cout << get_my_string() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

调用get_my_string会迫使你的静态字符串初始化只有一次(第一次调用函数),恰好在那个时候你需要它。请注意,此示例未考虑线程(在多线程应用程序中,您应同步get_my_string()函数以保护静态字符串的初始化)。

希望对您有所帮助。

顺便说一句:您的global可能会遇到类似的问题TestClass j

这样,您将只解决一半的问题 -初始化(您仍然不知道销毁的顺序)-但是在大多数情况下,这是足够的。

另一个选择是在堆上创建字符串(可能使用如上所述的类似方法)-您只需要delete在知道这样做是安全的时候就可以了。