c++ - 具有重复符号的 C++ 插件库上的段错误

标签 c++ gcc linker runtime shared-libraries

我有一个跨平台的 C++ 应用程序,它被分成几个共享库并从插件共享库加载附加功能。插件库应该是自包含的,并且在不了解或不依赖于调用应用程序的情况下自行运行。

其中一个插件包含从主应用程序复制的代码,因此包含与引擎中的名称重复的符号名称。 (是的,我知道这通常是一个禁忌,但在编写插件时,引擎是一个单一的二进制文件,无法共享库。)在 Windows 上,一切运行良好。在 Linux 上,我们遇到了段错误。通过查看错误的堆栈跟踪,它是在插件中调用重复类名中的函数时发生的。这似乎是引擎和插件的共享代码版本略有不同的结果(某些类功能在插件中被注释掉了)。就好像插件正在将它的符号运行时链接到引擎而不是它自己的。我们通过更改 dlopen 来“解决”这个问题。的参数为 dlopen(pFilepath, RTLD_LAZY | RTLD_LOCAL) .

但是当我们重写引擎以拆分为共享库时(为了最终在插件中重用),我们再次遇到段错误。查看堆栈跟踪,它从引擎 -> 插件 -> 引擎开始。

有没有办法指定运行时链接器不将插件的符号映射到引擎(特别是如果它们在插件中定义)?

谢谢! 马特


编辑于 2009-12-3

我首先尝试将插件的代码包装在它自己的命名空间中。这不起作用,因为它静态链接到也链接到引擎的库。静态库的版本不一样,导致segfault!

然后我更改了引擎的构建,并将其库更改为静态链接。当我运行它时,我不再有问题。所以看起来这是导出共享库符号然后在打开时动态重新定位到插件中的结果。但是,当引擎的所有代码都在单个可执行文件中时,它不会导出其符号(因此它不会尝试将插件的符号重新定位到引擎中)。

但我仍然有一个问题,因为有一个并行版本的程序(使用 Open-MPI)并且仍然会出现段错误。看起来它仍在导出引擎的符号并重新定位插件的符号。这可能与 Open-MPI 执行应用程序的方式有关。

是否有任何链接器标志可用于插件共享库,告诉它不要在运行时动态重定位符号?或者隐藏它的符号以免它们被重新定位?我试过了 -s (“省略所有符号信息”)但这显然没有改变动态符号(使用 nm -D <plugin> 检查)。

最佳答案

我想我找到了解决方案,链接器标志 -Bsymbolic。本质上,此标志在共享库中添加了一个标志,以告诉运行时链接器首先尝试在其自身内解析符号名称。当插件与该标志链接时,引擎能够在所有情况下(单片 exe、带共享库的 exe、带和不包装命名空间的插件)与插件一起运行。

似乎确实有一些批评者对 -Bsymbolic 发出了警告:
http://www.technovelty.org/code/c/bsymbolic.html
http://software.intel.com/en-us/articles/performance-tools-for-software-developers-bsymbolic-can-cause-dangerous-side-effects/

但考虑到他们的警告和插件的意图,我认为这对我来说是正确的选择。至少现在是这样。

关于c++ - 具有重复符号的 C++ 插件库上的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1821153/

相关文章:

编译时 float 打包/双关语

c - GCC 链接器问题与 -lm 标志

c++ - Lua 5.2 : undefined symbols when using luaL_dofile()

c++ - 实现方法时如何使用命名空间?

c++ - RapidJSON::Value&的GoogleTest/Mock SaveArg

c++ - 在 GCC 中链接库

c++ - 将带有 main() 的共享库链接到仅提供处理函数的可执行文件

c++ - 递归函数循环遍历字符数组

C++ OpenSSL HMACSHA1 可以工作,但不是我想要的

gcc - 在 cmake 中检查 gcc 次要