gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:23:57 24 4
gpt4 key购买 nike

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

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

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

这是我做的SSCCE:

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

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

int main()
{
return 0;
}

-

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

#include <string>

// global
extern const std::string S;

#endif // C_H_INCLUDED

-

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

#include <string>

// extern definition of global
const std::string S = "global string data";

-

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

class TestClass
{
public:
TestClass();
};

#endif // TESTCLASS_H_INCLUDED

-

/* 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
}

有关崩溃的调试器消息:

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

这个例子在 operator<< 中崩溃,但它在任何对 S 的引用上崩溃,无论它是如何被引用的。

最佳答案

我猜它崩溃是因为全局 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;
}

调用 get_my_string将强制初始化您的静态字符串仅一次(第一次调用该函数时)恰好在您需要它的时候。请注意,此示例未考虑线程(在多线程应用程序中,您应该同步 get_my_string() 函数以保护静态字符串的初始化)。

希望对您有所帮助。

顺便说一句:您可能会遇到与全局 TestClass j 类似的问题.

通过这种方式您将只解决一半的问题 - 初始化(您仍然不知道销毁的顺序) - 但在大多数情况下就足够了。

另一种选择是在堆上创建字符串(可能使用与上述类似的方法)——你只需要 delete在您知道这样做是安全的时候。

关于创建其构造函数引用全局变量的类的全局实例时,c++程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30836329/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com