卸载c++插件中的静态实例变量
unload a static instance variable in c++ plugin?
提前感谢。我现在正在用c++为一个大系统开发一个插件。在我的插件我有一些静态变量。我发现当它在Linux上以调试模式编译时,它工作得很好,没有任何问题。当它在RELEASE模式下编译时,即编译器做了一些优化,然后当我卸载插件时,静态变量不会被删除(静态变量类的析构函数永远不会被调用),所以内存永远不会被释放,下次当我重新加载插件时,它会导致主程序崩溃!
谁能解释一下为什么静态变量不销毁插件卸载时?注意:静态变量是静态实例,而不是指针!
class MySettings
{
public:
static MySettings& Instance() {
static MySettings theSingleton;
return theSingleton;
}
virtual ~MySettings();
}
在插件的某个地方,它像这样被调用
....
MySettings &s = MySettings::Instance();
s.xxx();
....
当我在调试模式下编译和运行时,我从析构函数中打印了一些信息,当插件被拔掉时,看起来实例被正确地析构了。但是当我在发布模式下编译和运行时,当插件被拔下时,永远不会调用析构函数。我不是插件管理器的开发者,不能说太多。非常感谢你的帮助!
下面是加载插件库的一段代码。
newLib._libHandle = ::dlopen(path_to_the_plugin_lib, RTLD_LAZY | RTLD_GLOBAL);
if(! newLib._libHandle) {
cerr << "dlopen failed for: " << path << " - "
<< ::dlerror();
return "";
我终于让它工作了。但还是不明白为什么。以下是我所做的:
class MySettings
{
public:
static MySettings& Instance() {
return theSingleton;
}
private:
static MySettings theSingleton;
virtual ~MySettings();
}
MySettings MySettins:theSingleton;
因为应用程序非常大,有数百万行代码。我的疑问是,当gcc以RELEASE模式编译时,优化出了问题。
我自己从来没有尝试过,文档似乎指定静态变量应该在重新加载时"重新初始化"。对我来说,它是如何与c++的pre- main()
钩子相互作用的,一点也不明显。您可以尝试理解这一点(检查供应商的文档,或者只是打开二进制文件并查看),但重新设计可能更简单。一些想法:
如果可以的话,去掉你的单例。正如评论中提到的,目前业界的共识是,大多数时候,单例模式带来的麻烦比它的价值要多——正如您所发现的那样!公平地说,在Java或Ruby中不会有这个问题,但是仍然。
如果你用gcc编译,你可以为"dlopen()
返回之前"answers"dlclose()
被调用之后"注册一些钩子。再次从文档:
...libraries should export routines using the __attribute__((constructor)) and __attribute__((destructor)) function attributes. See the gcc info pages for information on these. Constructor routines are executed before dlopen() returns, and destructor routines are executed before dlclose() returns."
我很确定这是gcc特有的;如果您不使用gcc,您的平台可能提供类似的功能。
如果你不能这样做,试着切换到单例实现的"首次使用初始化"风格。这个想法是在Instance()
中检测您的MySettings
单例是否已经创建,如果没有,则首先创建它。比如:
static MySettings* theSingleton = NULL;
if(theSingleton == NULL)
theSingleton = new MySettings();
return *theSingleton;
注意这个版本的Instance()
是不是线程安全的;如果你想那样做,你就得费点劲。另外:theSingleton
将永远不会被删除,所以你的问题会泄漏一些内存/文件描述符/无论你的插件每次重新加载。这取决于你在MySettings
中保留的东西,以及你希望用户在进程重启之间重新加载插件的频率,这可能是可接受的,也可能是不可接受的。
- C++两个源文件之间共享的枚举的静态实例
- 宏为模板类静态实例生成有效的标识符
- 我可以在类头文件中定义一个类的const静态实例吗
- 类的静态实例不能调用私有成员函数.C++
- 第二个dll中的静态实例的破坏者未被调用
- 类的静态实例无法在程序退出时正确处理资源删除
- C++:外部类中内部类的静态实例
- 结构定义包含自身的静态实例
- 什么是C++中C#静态实例的等价物
- 父类包含子类C++的静态实例
- 在C++中创建静态实例的未解析外部
- 多个对象的静态实例变量-c++
- 在c++中,一旦程序退出,singleton(静态实例)就会被销毁,这是正确的原因
- 对从静态实例引用的类模板的静态成员的未定义引用
- 在类自身内部创建类的静态实例的正确方法
- 初始化模板类中嵌套类的静态实例
- 卸载c++插件中的静态实例变量
- 在c++ STL类型的静态实例上使用OpenMP threadprivate指令
- 我的类的静态实例函数不像我预期的那样工作
- 保留子类的中心列表,但避免静态实例