静态库的静态成员

5

我是一个有用的助手,可以为您翻译文本。

我有一个带有静态成员的静态库。该库被静态链接到主应用程序和其中一个插件中。看起来静态变量在主应用程序和dll(插件)中都进行了初始化。

问题:如何避免动态库加载时静态变量重新初始化。或许我错过了一些简单的东西?

更多信息:

这是一个简单的静态库,包含静态成员及其getter和setter:

orbhelper.h

class ORBHelper {
    static std::string sss_;
public:
    static std::string getStr();
    static void setSTR(std::string str);
};

orbhelper.cpp

std::string ORBHelper::sss_ = "init";

static std::string ORBHelper::getStr()
{
    std::cerr << "get " << sss_.c_str() << std::endl;
    return sss_;
}
static void ORBHelper::setSTR(std::string str)
{
    sss_ = str;
    std::cerr << "set " << sss_.c_str() << std::endl;
}

这个库被用在main.cpp和另一个动态库中,这个动态库被加载到main中。 在main.cpp中,我设置了一个静态字符串,并且在其中一个动态库函数中,我想要获取它。
在main中设置静态变量:
main.cpp
...
ORBHelper::setStr("main");
std::cerr << ORBHelper::getStr().c_str() << std::endl; //prints 'main'
//then loading library
...

接下来在dll中获取变量的值:

hwplugin.cpp

...
std::cerr << ORBHelper::getStr().c_str() << std::endl; //prints 'init' instead of 'main'
...

看起来静态变量被初始化了两次。第一次是在main.cpp之前,第二次是在动态库加载时。静态库中的静态类链接到主应用程序和动态库上。
注:我的问题中有太多“静态”这个词了,我知道 =)

如果您进行静态链接,可能会得到两个变量实例,一个在可执行文件中,另一个在DLL中。 - Bo Persson
我检查了一个变量的地址(printf("%p",&sss);),发现它是同一个变量。 - uni
2
我最近也遇到了同样的问题(http://stackoverflow.com/q/10520587/509868);获得了两个可用的解决方案:1. 将静态库转换为另一个DLL;或者2. 在现有的DLL中添加一个函数,以初始化静态库中的有问题的东西。 - anatolyg
1
如果您有运行时加载,建议在主应用程序中构建一些全局上下文对象,然后将引用或指针传递给动态库初始化。上下文对象可以轻松包含足够的状态信息,以使每个已加载的库能够确定是否需要执行更多操作。 - Kerrek SB
1个回答

0

是的,你有两个帮助类实例。

DLL 应该链接到链接静态类并使用它来解析帮助类的可执行文件。不要将 DLL 与静态库链接,而是将其链接到可执行文件本身。


你不能这样做,当构建dll时会出现链接器错误。 - Matteo Italia
我在helper的每个函数中添加了printf("%p",&sss_),每次它都打印相同的地址。这不意味着只有一个helper实例吗? - uni
嗯...可能吧,但是即使符号映射到相同的内存地址,静态初始化程序仍然会运行两次。 - Antti Huima

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接