模板类函数中的静态变量被全局静态变量覆盖

Static variable in template class function overwritten by global static variable

本文关键字:静态 变量 全局 覆盖 类函数      更新时间:2023-10-16

在模板类函数中有一个静态变量:

template<class T>
struct builder 
{
    static T* buildOrGet() 
    { 
        static T* built = nullptr;
        if(built == nullptr) built = new T;
        return built;
    }
};

和代码中其他地方的一个带构造函数的全局变量

static SomeClass global_var;

起初我不知道发生了什么,但是built变量在程序的某个点毫无原因地损坏了。然后,我在&built上的visual studio中添加了一个4字节的数据断点,以查看built = new T;之后谁破坏了它的内存,实际上它是在初始化global_var成员时的c++动态初始化期间,在SomeClass构造函数中。代码在dll中,由依赖它的exe自动加载。这就像global_var内存和built内存重叠,非常奇怪。

我真的不明白为什么会发生这种情况,除了Visual Studio 2015中的一个bug,你能帮助我吗?

我找到了解决方案:事实上,我在我的dll的不同翻译单元中有多个具有相同名称的global_var,但它们没有相同的类型(假设另一个具有int类型)。

在这种情况下(这对我来说很奇怪,因为它们是'静态'),链接器只是保留一个,并为所有变量使用相同的内存(它在这里保留了int一个)。

这就是它出错的地方…我上面提到的global_var仍然调用SomeClass构造函数,但它的内存不是sizeof(SomeClass),而是sizeof(int),并且这就是溢出发生的地方

对我来说,这是一个bug,因为链接器应该注意到这些具有不同类型或/的同名变量,并且应该避免在与构造内存不匹配的变量上调用构造函数。

解决方案是:永远不要在不同的翻译单元中声明两个具有相同名称的静态变量,只有一个会存活,并且您无法猜测是哪一个。