【问题标题】:Static variable not initialized静态变量未初始化
【发布时间】:2010-04-27 10:51:39
【问题描述】:

我有一个静态变量的奇怪问题,它显然没有按应有的方式初始化。
我有一个在 Windows 和 Linux 上运行的大型项目。由于 Linux 开发人员没有这个问题,我建议这是某种有线 Visual Studio 的东西。

头文件

class MyClass
{
    // some other stuff here
    ...
    private:
        static AnotherClass* const Default_;
};


CPP 文件

AnotherClass* const MyClass::Default_(new AnotherClass(""));
MyClass(AnotherClass* const var)
{
    assert(Default_);
    ...
}

问题是Default_总是NULL。我还在该变量的初始化处尝试了一个断点,但我无法捕获它。

另一个班级也有类似的问题。
CPP 文件

std::string const MyClass::MyString_ ("someText");
MyClass::MyClass()
{
    assert(MyString_ != "");
    ...
}

在这种情况下,MyString_ 始终为空。所以再次没有初始化。
有人对此有想法吗?这是 Visual Studio 设置问题吗?
干杯西蒙

编辑:
我还遇到了静态初始化惨败。但我不确定这是否是问题所在,因为 Linux 编译器没有问题。在这种情况下编译器不应该以同样的方式做出反应吗?

【问题讨论】:

  • 尝试从头开始创建一个新项目,看看是否也会发生这种情况
  • 对不起,做不到。正如我所说,这是一个非常庞大的项目。
  • 我认为第一个例子是一个错字,应该是AnotherClass* const MyClass::Default_(new AnotherClass(""));
  • 您仍然可以尝试使用静态成员创建一个新的空测试项目,然后查看它是否正确初始化...
  • 代码是否在静态库中?如果依赖的程序没有引用类 MyClass (确切地说是编译单元),那么你会遇到问题。然后链接器不会为变量创建静态初始化代码。

标签: c++ visual-studio-2008 static variables


【解决方案1】:

我建议你使用带有静态变量的静态成员函数,而不是静态变量本身:

class MyClass
{
    // some other stuff here
    ...
    private:
        static AnotherClass* const getAnotherClass();
};

AnotherClass *const MyClass::getAnotherClass()
{
    static AnotherClass *const p = new AnotherClass("");
    return(p);
}

标准保证 p 在第一次调用函数时被初始化一次,所以你总是会得到正确初始化的对象(除非你已经耗尽了内存或者你的构造函数抛出了)。

请注意 - 这可能是线程安全的,也可能不是线程安全的(取决于你的编译器)。

还有一个注意事项 - 现在你必须忍受“内存泄漏”,因为几乎不可能决定何时销毁对象,而且你无法将 p 重置为 NULL。

【讨论】:

  • 在这种情况下使用指针是不好的。一个简单的实例化然后返回一个引用会好得多。毕竟,一旦您删除了 NULL 可能性,* const 的语义不就等同于 & 吗?
  • @Matthieu:我只是按照给出的代码。对于您的评论-您可能是对的,但这实际上取决于 AnotherClass 的作用(例如,它可能会占用您数据段中的所有空间,因此没有其他全局变量可用)。
  • 我同意可能需要使用 heap 以免数据段或堆栈饱和(我有点希望 Go 在这里... ) 但是我认为它应该保留给特殊情况(大物体)并推迟到必要时。
  • 关于静态 AnotherClass 与指向 AnotherClass 的静态指针的另一个注意事项:当您使用指针时,该对象很可能会在程序生命周期内保留,并且它的析构函数可能不会被调用,除非照顾那。当对象拥有您必须手动释放的系统资源时,这可能是一个问题。对于静态对象,析构函数将被调用,但您不知道也无法控制它何时发生,这可能会导致您的静态破坏命令惨败。
【解决方案2】:

如果在初始化其他一些静态变量时发生这种情况,您可能会看到static initialization fiasco

【讨论】:

  • 这是与 Visual Studio 编译器相关的问题吗?还是一般问题?
  • @Simon:这是一个普遍的问题。
  • 所以这不是我的问题,因为 Linux 开发人员没有类似的问题......
  • @Simon:基本上,如果您有不同的编译单元/目标文件,则不能保证它们以特定顺序初始化。因此,如果一个目标文件中的静态变量首先被初始化,然后他们尝试使用其他尚未初始化的静态变量,就会出现问题。该顺序是未定义的,因此它可能会或可能不会与另一个编译器“工作”,一旦您将文件添加到项目或更改其他内容,这可能会改变。由于初始化顺序基本上是随机的,如果它没有出现在某些特定的构建中,问题很可能也存在。
【解决方案3】:

在这种情况下编译器不应该以同样的方式做出反应吗?

没有。据我了解,各个编译单元的初始化顺序是未定义的。所以 Linux 开发人员很幸运。今天。明天,谁知道呢?

【讨论】:

    【解决方案4】:

    在我的机器上工作(TM):

    #include <iostream>
    #include <cassert>
    
    class AnotherClass
    {
    public:
        AnotherClass(const char*) {}
    };
    
    class MyClass
    {
    public:
        MyClass(AnotherClass* const var);
    private:
        static AnotherClass* const Default_;
    };
    
    AnotherClass* const MyClass::Default_(new AnotherClass(""));
    
    MyClass::MyClass(AnotherClass* const var)
    {
        assert(Default_);
        std::cout << "Worked!\n";
    }
    
    int main()
    {
        MyClass tester(NULL);
        return 0;
    }
    

    我想问题是MyClass::MyClass() 被称为另一个静态变量的构造函数。静态变量的初始化并不总是按照您希望的顺序进行。

    【讨论】:

    • 但在他的第二个例子中,他记得MyClass::,所以这可能只是问题中的一个错字。
    • 您提到调用可能在另一个静态变量的构造函数中。我仍然必须检查这个。但是Linux编译器不应该是同样的问题吗?
    • @Simon:如果这是一个静态初始化问题,那么结果是 undefined。这意味着它可能在一种情况下有效,但在另一种情况下则无效。如果您不认为这是一个静态初始化问题,那么我唯一能想到的就是复制代码,并逐个删除其中的一些,这样问题仍然存在,直到您到一个重现问题的小例子。通常问题是这样发现的。如果没有,请在它足够小的时候发布在此处,以便其他人可以查看。
    猜你喜欢
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 2011-08-22
    • 2010-12-22
    • 1970-01-01
    • 2010-12-11
    相关资源
    最近更新 更多