【发布时间】:2019-03-05 17:19:06
【问题描述】:
(这大概是一个相当高级的问题,对此感到抱歉:-))
我有一个问题,我需要将插件(共享库)加载到应用程序中,但插件可能使用与应用程序使用的库版本二进制不兼容的库。我的想法是使用 dlmopen() 并将插件加载到它自己的命名空间中。我希望获得二进制不兼容库的两个单独副本(以及任何其他常见依赖项,即使二进制兼容)。
这似乎在一定程度上起作用,但在某些情况下,我在 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++ 库的新命名空间?非常欢迎任何形式的输入如何从这一点继续!
【问题讨论】:
-
你能告诉我们你目前用来加载插件的代码吗?另外,打开成功了吗?如果您在打开失败时尝试调用插件中的函数,这可能就是它会崩溃的原因。
-
@AlexisWilke 未检查打开,但也未使用生成的句柄。
-
替代解决方案:在与该库兼容的单独可执行文件中加载不兼容的库。违反 ODR 的拨号并不好玩。
-
@AlexisWilke:代码包含在示例中,请参见链接。打开没有完成,因为它内部有段错误(加载库时调用 dl_init)。
-
我认为
dlmopen是一个相当老套的功能。 GDB 开发人员在某处发表评论称,他们没有对通过dlmopen加载的二进制文件进行调试提供适当的支持,因为他们找不到使用它的人。
标签: c++ linux plugins dynamic-loading