dlclose() 不调用全局对象的析构函数

2024-04-20

插件1.cpp:

#include <iostream>

static class TestStatic {
public:
  TestStatic() {
     std::cout << "TestStatic create" << std::endl;
  }
  ~TestStatic() {
     std::cout << "TestStatic destroy" << std::endl;
  }
} test_static;

host.cpp

#include <dlfcn.h>
#include <iostream>
int main(int argc,char *argv[]) {
   void* handle = dlopen("./plugin1.so",RTLD_NOW | RTLD_LOCAL );
   dlclose(handle);
   return 0;
}

构建并运行:

>g++ -c plugin1.cpp -o plugin1.o -fPIC
>g++ -shared plugin.o -o plugin1.so
>g++ host.cpp -o host -ldl
>./host
>TestStatic create
>Segmentation fault

为什么 TestStatic::~TestStatic 在 'exit()' 处调用而不是在 'dlclose()' 处调用?


C++ 标准要求当程序以相反的构造顺序退出时,为全局对象调用析构函数。大多数实现都通过调用 C 库 atexit 例程来注册析构函数来处理此问题。这是有问题的,因为 1999 C 标准只要求实现支持 32 个注册函数,尽管大多数实现支持更多。更重要的是,它根本不涉及在大多数实现中通过在程序终止之前调用 dlclose 从正在运行的程序映像中删除 DSO 的能力。

此问题在 GCC 的后续版本(包括 C/C++ 标准库和链接器)中得到解决。基本上,C++ 析构函数应该使用__cxa_atexit函数而不是atexit (3).

有关完整的技术细节__cxa_atexit, see 安腾 C++ ABI 规范 http://en.wikipedia.org/wiki/POSIX.


从您的问题中不清楚您正在使用什么版本的 gcc、链接器和标准 C 库。另外,您提供的代码不符合POSIX http://en.wikipedia.org/wiki/POSIX标准,因为没有RTDL_NOW or RTDL_LOCAL宏定义。他们是RTLD_NOW and RTLD_LOCAL (see dlopen http://www.opengroup.org/onlinepubs/009695399/functions/dlopen.html).

如果你的C标准库不支持__cxa_atexit,您可能需要通过指定来禁用它-fno-use-cxa-atexit海湾合作委员会标志:

-保险丝-cxa-atexit

为具有静态存储的对象注册析构函数 __cxa_ atexit 的持续时间 函数而不是 atexit 功能。此选项是必需的 完全符合标准的处理 静态析构函数,但只能工作 如果你的 C 库支持 __cxa_atexit。

但这可能会导致析构函数以不同的顺序调用或根本不调用的问题。所以万一损坏的最佳解决方案__cxa_atexit支持或根本不支持就是不要在共享库中使用带有析构函数的静态对象。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

dlclose() 不调用全局对象的析构函数 的相关文章

随机推荐