1

我刚刚升级到第三方库的新版本(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为空。

我不认为这是可能的!有任何想法吗?

4

1 回答 1

5

看起来您已经在头文件中定义了函数,并且包含在许多.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_theFunctionis not static(并且在 中定义proxy.cpp),它只有一个版本;没有其他版本。由于您调用的只有一个代理,因此您每次theFunction()调用的都是相同版本,因此每次调用theFunction都会看到相同版本的static变量。:-)

于 2013-01-22T17:38:13.097 回答