C++ 静态函数中的静态变量能否移动到内存中的新地址?
我刚刚升级到一个新版本的第三方库(Qt5.0版的QtPropertyBrowser)。升级导致了我的应用程序中的一个新错误,我设法跟踪到库中的一个静态函数。该函数包含一个静态变量,该变量在第一次调用该函数时初始化。我在初始化后复制了该变量的内存位置,正如预期的那样,在多次后续调用中发现该变量仍保留在同一内存位置。然后在随后的函数调用中,我注意到静态变量中的内存位置和数据发生了变化(导致程序中出现错误) 代码如下所示:C++ 静态函数中的静态变量能否移动到内存中的新地址?,c++,C++,我刚刚升级到一个新版本的第三方库(Qt5.0版的QtPropertyBrowser)。升级导致了我的应用程序中的一个新错误,我设法跟踪到库中的一个静态函数。该函数包含一个静态变量,该变量在第一次调用该函数时初始化。我在初始化后复制了该变量的内存位置,正如预期的那样,在多次后续调用中发现该变量仍保留在同一内存位置。然后在随后的函数调用中,我注意到静态变量中的内存位置和数据发生了变化(导致程序中出现错误) 代码如下所示: class ClassA { //.... }; class Cl
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调用函数。也就是说,不是直接调用函数,而是调用代理(它是在单个翻译单元中定义的,没有更多版本)
- 在标头中声明代理:
//proxy.h ClassA *proxy_of_theFunction();
- 在实现文件中定义代理:
//proxy.cpp ClassA* proxy_of_theFunction() { return theFunction(); //call the actual function }
静态
(它在proxy.cpp中定义),因此它只有一个版本;没有其他版本。由于只有一个代理可以调用theFunction()
,因此每次调用的theFunction
都是相同版本的,因此每次调用都会看到相同版本的static
变量。:-) 看起来您已经在头文件中定义了函数,并且包含在许多.cpp
文件中(每个.cpp
文件定义了一个翻译单元)
由于函数声明为static
,因此每个翻译单元都有自己的版本以及static
变量。这就是为什么当您从不同的转换单元调用函数时,静态变量的地址是不同的。只要你从同一个翻译单位打电话,你就会看到同一个地址
请注意,对于特定的翻译单元,地址将保持不变。只是每个翻译单元都有自己的静态变量版本,因此地址不同;您不再访问同一个变量,它们是具有相同标识符的不同变量
问题是,这些都是在第三方库中定义的,我需要在不重新初始化静态变量的情况下从dll和exe调用它。有没有什么方法可以在不改变库中代码的情况下解决这个问题?我目前正在将库用作.lib。如果我把它编译成.dll,问题会消失吗 为了避免静态函数的多个版本(因此是静态变量),您需要从同一个转换单元调用它。要做到这一点,可以使用proxy调用函数。也就是说,不是直接调用函数,而是调用代理(它是在单个翻译单元中定义的,没有更多版本)
- 在标头中声明代理:
//proxy.h ClassA *proxy_of_theFunction();
- 在实现文件中定义代理:
//proxy.cpp ClassA* proxy_of_theFunction() { return theFunction(); //call the actual function }
由于函数的是而非
静态
(它在proxy.cpp中定义),因此它只有一个版本;没有其他版本。由于只有一个代理可以调用theFunction()
,因此每次调用的theFunction
都是相同版本的,因此每次调用都会看到相同版本的static
变量。:-) 上面哪一部分在头文件和cpp文件中?最初,所有内容都在头文件中模板化,并使用复杂的宏调用。为了调试正在发生的事情,我复制了没有模板或宏的类和函数,并将它们全部放在相关的.cpp文件中。这两种情况下的问题是相同的。为了澄清,您是说静态变量本身的地址(&statVar
)发生了变化?或者它内部指向ClassA
的指针发生了变化?第二个很容易解释,因为每次调用函数时都会覆盖它;第一个更神秘,你创建了一个新的ClassA