(这大概是一个相当高级的问题,对此表示抱歉:-))

我有一个问题,我需要将插件(共享库)加载到应用程序中,但是插件可能使用的库与应用程序使用的库的版本二进制不兼容。我的想法是使用dlmopen()并将插件加载到其自己的 namespace 中。我希望获得二进制不兼容库的两个单独副本(以及任何其他常见的依赖关系,即使二进制兼容)。

这似乎可以达到一定程度,但是在某些情况下,在静态对象的构造函数被调用时(这是我在调试器中发现的),在glibc的深处出现了段错误。

我做了一个最小的例子来重现这个问题,可以在github上找到它:https://github.com/mhier/segregatedLinkingExample

该示例使用libxml++作为外部通用C++库,因此您将需要安装其开发包。运行“mk.sh”进行编译,然后运行“main”。然后它将崩溃(至少在Ubuntu 16.04和18.04上会崩溃)。如果删除“-DWITH_CRASH”,它不再崩溃。

WITH_CRASH编译开关允许在主要可执行文件中使用libxml++。它始终在插件库libC中使用。主可执行文件和插件都只使用libxml++,我看到了崩溃。在这种情况下,“使用”只不过是从虚拟类派生一个虚拟类,并确保通过实现构造函数/析构函数确实为派生类生成了代码。它甚至没有在插件中执行代码(除了通过dl_init->静态对象的构造函数等)。

我在Internet上找不到关于dlmopen的很多信息。我没有找到指向正确方向的错误报告。有没有人曾经将dlmopen与C++库的新命名空间一起使用?从现在开始如何继续进行任何形式的输入都非常欢迎!

最佳答案

因此,似乎答案是不这样做。 dlmopen似乎与C++有关,可能导致未定义的行为。大概是因为 namespace 无法完全解决ODR违规问题。

我承认,这个答案是我的主观看法。我没有找到关于将dlmopen用于C++库的许多很好的资源。因此,我的结论是不使用它,因为我需要它可靠地工作。我看到了非常奇怪的效果,例如如果我将共享库链接到特定的第三方库(即使不使用它),则该问题中的示例将再次起作用。除非我能理解这些影响,否则我将不信任任何解决方案(因为它可能会偶然起作用)。

dlmopen()可能在其他环境下工作,例如是否同时控制应用程序和共享库,并可以测试它是否正确加载。

关于c++ - dlmopen和C++库,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55008283/

10-11 01:28