静态函数中的静态变量可以移动到内存中的新地址吗?

Can a static variable in a static function move to a new address in memory?

本文关键字:地址 新地址 变量 静态 静态函数 移动 内存      更新时间:2023-10-16

我刚刚升级到一个新版本的第三方库(QtPropertyBrowser for Qt 5.0)。升级导致我的应用程序出现了一个新的错误,我设法跟踪到库中的一个静态函数。函数包含一个静态变量,该变量在第一次调用函数时初始化。在初始化之后,我复制了该变量的内存位置,并发现,正如预期的那样,在随后的多次调用中,该变量保持在相同的内存位置。然后在随后的函数调用中,我注意到静态变量中的内存位置和数据发生了变化(导致程序中的错误)。

代码看起来像这样:

class ClassA
{
    //.... 
};
class ClassB
{
public:
    ClassA* ptrMember;
};
static ClassA *theFunction()
{
    static ClassB statVar = {0};
    if(!statVar.ptrMember)
        statVar.ptrMember = new ClassA();
    return statVar.ptrMember;
}

我发现在多次调用theFunction()时,存储在&statVar中的地址始终保持不变,但随后调用&statVar中的地址不同,statVar.ptrMember为空。

我不认为这是可能的!什么好主意吗?

看起来您已经在头文件中定义了函数,并包含在许多.cpp文件中(每个.cpp文件定义了一个翻译单元)。

由于函数声明为static,每个翻译单元都有自己的版本和static变量。这就是为什么从不同的转换单元调用函数时,静态变量的地址是不同的。只要从相同的翻译单元调用它,就会看到相同的地址。

请注意,对于特定的翻译单元,地址将保持不变。只是每个翻译单元都有自己版本的静态变量,因此地址不同;不是访问相同的变量,它们是具有相同标识符的不同变量。


问题是这都是在第三方库中定义的,我需要从dll和exe中调用它,而不需要重新初始化静态变量。有什么办法,我可以照顾的问题,而不改变在库中的代码?我目前使用的库作为。lib。如果我将其编译为.dll,问题会消失吗?

为了避免多个版本的静态函数(因此是静态变量),您需要从相同的翻译单元调用它。为此,您可以使用代理来调用该函数。也就是说,不是直接调用函数,而是调用代理(它在单个翻译单元中定义,没有其他版本)。

  • 在报头中声明代理:

    //proxy.h
    ClassA *proxy_of_theFunction();
    
  • 在实现文件中定义代理:

    //proxy.cpp
    ClassA* proxy_of_theFunction()
    {
        return theFunction(); //call the actual function
    }
    

呼叫proxy_of_theFunction。这应该能解决你的问题。

由于proxy_of_theFunction而不是 static(它在proxy.cpp中定义),所以它只有一个版本;没有其他版本。由于只有一个代理可以调用theFunction(),因此每次调用theFunction相同的版本,因此每次调用都将看到相同的版本的static变量。: -)