使用`dlopen`重新加载运行时库

Zoh*_*r81 6 c++ macos dynamic-linking dlopen

基于c ++的运行进程是否可以使用重新加载基于c ++的动态库dlopen.

正在运行的进程将轮询新版本的动态库(使用相同的API).一旦检测到此类文件,就会发生以下一系列操作:

  1. 使用旧版库卸载 dlclose
  2. 复制较新的dylib并覆盖旧版本的文件.
  3. 该过程使用从该位置加载较新版本 dlopen
  4. 根据dlsym新加载的库设置函数指针变量.

在最后一个阶段,我实际上获得了所需的API并将其放在我的主代码中的函数指针中,以便稍后使用.

但是,似乎我的程序在第三阶段后意外地崩溃了.是否可能该dlclose部分在流程虚拟空间中留下旧库的一些残余?有没有更好的方法呢?

顺便说一句,在Windows中它使用LoadLibrary, FreeLibrary and GetProcAddress而不是使用dlopen, dlclose and dlsym.

Max*_*kin 5

好像我的程序在第三阶段后意外地崩溃了.是否可能该dlclose部分在流程虚拟空间中留下旧库的一些残余?

有可能的.具有函数指针的对象和具有在被卸载的库中定义的虚函数的对象将最终得到无效指针.更糟糕的是,可以将新方面附加到标准流(例如std::cout),然后卸载实现方面的共享库.稍后在使用std::cout不相关的地方时会崩溃(真实的故事).因此,您必须完全控制共享库的功能.

此外,dlopen必须调用RTLD_LOCAL,以便其他任何东西都不能(意外地)使用正在加载的共享库的符号并防止它被卸载.man dlopen如果你做了这样的专长,你必须阅读并理解.

  • GCC还可以输出[唯一符号](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66830),即使使用*`RTLD_LOCAL`也可以防止卸载*.当使用`nm`时,这些显示为"u".最常见的是,这些是`inline`函数和/或函数模板中的`static`变量.我们有这个问题,只有标题库,如Boost的一部分,但我的同事也设法创建这些.问题是如果插件是第一个引入它们的DSO,它永远不会被卸载.`dlclose`成功但二进制​​仍然映射. (2认同)