Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 卸载c+中的静态实例变量+;插件?_C++_Plugins_Static_Instance_Destroy - Fatal编程技术网

C++ 卸载c+中的静态实例变量+;插件?

C++ 卸载c+中的静态实例变量+;插件?,c++,plugins,static,instance,destroy,C++,Plugins,Static,Instance,Destroy,提前谢谢。我现在正在开发一个C++大系统的插件。在我的插件中,我有一些静态变量。我发现,当它在Linux上以调试模式编译时,它运行良好,没有任何问题。当它在发布模式下编译时,即编译器进行了一些优化,然后当我卸载插件时,静态变量不会被删除(静态变量类的析构函数永远不会被调用)。因此,内存永远不会被释放,下次我重新加载插件时,它会导致主程序崩溃 有人能解释一下为什么在卸载插件时静态变量没有被破坏吗?注意:静态变量是静态实例,不是指针 class MySettings { public:

提前谢谢。我现在正在开发一个C++大系统的插件。在我的插件中,我有一些静态变量。我发现,当它在Linux上以调试模式编译时,它运行良好,没有任何问题。当它在发布模式下编译时,即编译器进行了一些优化,然后当我卸载插件时,静态变量不会被删除(静态变量类的析构函数永远不会被调用)。因此,内存永远不会被释放,下次我重新加载插件时,它会导致主程序崩溃

有人能解释一下为什么在卸载插件时静态变量没有被破坏吗?注意:静态变量是静态实例,不是指针

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 "";

应用程序非常庞大,有数百万行代码。我的疑问是,当gcc在发布模式下编译时,优化出现了问题。

我自己从未尝试过,似乎指定在重新加载时应“重新初始化”静态变量。我一点也不清楚它是如何与C++的pre-
main()
hook交互的。您可以尝试理解这一点(查看供应商的文档,或者打开二进制文件查看),但重新设计可能更简单。一些想法:

如果可以,摆脱单身汉。正如在评论中提到的,现在业界的共识是,大多数时候,单身模式比它的价值更麻烦——正如你所发现的!公平地说,在Java或Ruby中不会有这个问题,但仍然存在

如果您使用gcc进行编译,则可以为“before
dlopen()
returns”和“before
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()
不是线程安全的;如果你想那样,你就得找点麻烦。另外:
singleton
将永远不会被删除,因此每次重新加载插件时,您的问题都会泄漏一些内存/文件描述符/任何东西。根据您在MySettings中保存的内容的种类,以及您希望用户在进程重启之间重新加载插件的频率,这可能是可以接受的,也可能是不可以接受的


希望这有帮助。

class MySettings{public:static MySettings&Instance(){static MySettings theSingleton;return theSingleton;}virtual~MySettings();编辑问题并在此处添加此信息!这取决于插件的加载方式。插件的用途是什么?出于测试目的,我将使用指针而不是引用,然后在不再需要插件时将其删除。是否有任何原因不使用指针?没有具体原因使用引用。是的,当我使用指针时,以及然后在我的插件卸载时删除,它确实工作得很好。我不明白的是,为什么在插件卸载后使用引用时它没有被破坏。非常感谢!谢谢你的回答。我尝试了你创建singleton的方法,但遇到了另一个问题。MySettings的构造函数没有初始化所需的所有内容,som一种延迟初始化。在我的用例中,我需要设置一些初始值,因此在new MySettings()之后,我立即调用该方法初始化一些私有成员,这涉及到为它们分配内存。然后我得到了类似内存溢出的结果,它会立即使应用程序崩溃。
static MySettings* theSingleton = NULL;
if(theSingleton == NULL)
  theSingleton = new MySettings();
return *theSingleton;