如何在Linux下使共享库自行重新加载

4
我正在Linux下开发一个C++共享库。
有没有办法让共享库代码在新的构建可用时重新加载自己?
我考虑使用dlclose和dlopen来重新加载,但前者需要一个仅对运行进程可访问的句柄。
你有什么想法如何从共享库代码中检索该句柄?整个想法是否有更好的解决方案?
我知道热交换很危险,但这将使开发和测试更加容易。
1个回答

5
重新构建共享库时,其导出的符号地址可能会发生更改。
因此,在重新加载共享库时,必须重新解析其用户导入的所有符号。
存储在共享库中的具有虚拟表的对象必须在卸载共享库之前进行销毁[1]。
如果该库是由ld.so自动加载的,则无法重新加载它。
如果应用程序使用dlopen加载共享库,则必须再次运行相同的代码以重新加载库并重新解析符号。
还有可能使事情变得复杂的线程局部存储。
换句话说,让重新加载共享库工作而应用程序不知道这一点太复杂了。
[1] 我曾经调试过一个有趣的错误。有一个共享库是在运行时使用dlopen加载的,并在使用后卸载。应用程序稍后在终止期间在std :: cout析构函数中崩溃。原来,该共享库将Boost.Date_Time对象输出到std :: cout中。这样做时,库将为具有自定义facet对象的新locale设置std :: cout.imbue(facet具有虚拟函数)。当库被卸载时,facet对象仍然拥有该locale,并且其vtable指针引用已卸载的共享库中的虚拟表,这将导致销毁facet时崩溃。

谢谢 @Maxim。是的,该应用程序使用dlopen加载库,我可以在strace中看到。很好的观点!我每次重新加载后都必须解决符号,这使事情稍微复杂了一些。 - ZeroCool
有趣的例子-非常好地突出了影响。 - ZeroCool

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接