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

时间:2018-03-14 14:50:40

标签: c++ macos dynamic-linking dlopen

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

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

  1. 使用dlclose
  2. 卸载旧版库
  3. 复制较新的dylib并覆盖旧版本的文件。
  4. 该过程使用dlopen
  5. 从该位置加载较新版本
  6. 根据新加载的库中的dlsym设置函数指针变量。
  7. 在最后一个阶段,我实际上获得了所需的API并将其放在我的主代码中的函数指针中,以便稍后使用。

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

    顺便说一句,在Windows中,使用LoadLibrary, FreeLibrary and GetProcAddress代替dlopen, dlclose and dlsym工作得很好。

1 个答案:

答案 0 :(得分:5)

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

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

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