c++ - 加载具有相同静态链接函数的两个共享库时使用哪个函数

标签 c++ linux gcc shared-libraries symbols

我一直在阅读并试图了解符号是如何在 Linux 的共享库中解析的。所以这里是我所面临的情况的描述。

我正在使用一个应用程序(APP),它可以加载用户创建的共享库以添加功能。我有两个这样的库,LIB_A.soLIB_B.so,它们执行单独的操作并且不依赖于另一个库来工作。它们是独立编译的,并且基于编译器参数(-fPIC),看起来它将使符号可插入(来 self 对该主题的研究)。因此大多数符号将默认导出。

现在,LIB_ALIB_B 使用的通用代码已编译并与每个库静态链接。公共(public)代码不使用任何 namespace 或静态函数,因此我假设它们也将被导出。 LIB_A 和 LIB_B 均按应用程序中的预期加载和工作。

但是如果公共(public)代码中发现了错误,但只有LIB_A可以重新编译,因为它需要固定代码,该怎么办?我的问题是,当重新编​​译LIB_A以获取公共(public)代码中的此更改并加载到APP中时,是否会有单独的拷贝LIB_A(已修复错误)和 LIB_B(未修复错误)的通用代码,并且每个都将使用各自的拷贝或都链接并在两者中共享公共(public)代码的版本之一?有没有办法让我使用调试器来发现符号的来源?

为了提前回答问题,我不知道库将以哪个顺序加载,我无法重新编译 LIB_B 来获取更改,只能重新编译 LIB_A。我没有APP的源代码,不知道它是如何动态加载库的。

我知道编译器标志有很多内容,但假设它只是 -fPIC,没有 -fvisibility-hidden-Wl、-Bsymbolic-fno-semantic-interposition 标志已设置。如果发生冲突,这些可以解决这个问题吗?

我查看了使用nm -D命令,我看到一些符号是W,这是否意味着它会使用现有符号(如果它在使用静态构建的符号之前已经存在)与图书馆?

我一直在阅读文章和搜索,但这一件事我不确定我是否 100% 确定。

编辑有关更多信息,我将在运行时按需加载这些库。使用 dlopenRTLD_LOCALRTLD_GLOBAL 相比,这会改变什么吗?从描述来看,RTLD_LOCAL似乎阻止了全局加载符号,因此不会与库外的其他符号发生冲突或链接?

最佳答案

Would there be separate copies of the common code for both LIB_A (that has the bug fix) and LIB_B (that does not have the bug fix)

缺少 -fvisibility=hidden (或您提到的其他类似标志) 运行时链接器将确保所有重复符号都解析为相同的实现(在 LIB_A 或 LIB_B 中)。 因此库将有效地共享代码。

Is there a way for me to discover the source of the symbol using a debugger perhaps?

通常,符号将从第一个加载的提供它们的库(LIB_A 或 LIB_B)中获取。 库将按照可执行文件的 .dynamic 部分中列出的顺序加载(运行 readelf -d app 以确保或简单地使用 LD_DEBUG 变量设置为 symbols)。 如果您想强制先加载LIB_A,可以相应地设置LD_PRELOAD

I know there is a great deal with the compiler flags but assume it's just -fPIC, no -fvisibility-hidden, -Wl,-Bsymbolic, -fno-semantic-interposition flags are set. Would these solve this issue if there was a conflict?

我假设您希望每个库使用它自己版本的通用符号? 实现此目的的最标准方法是-fvisibility=hidden。这将防止导出公共(public)符号 然后它们将被静态解析为本地拷贝。 当然,然后您需要查找并注释其他需要导出的函数。

-Bsymbolic 也可能有帮助,但这会强制解析所有本地可解析的引用 即您无法将其限制为您感兴趣的符号子集。 而且它的使用也不太广泛。

至于-fno-semantic-interposition,我手头没有最近的GCC,但我的印象是它是一个优化标志 对于编译器来说,通常不保证符号的本地解析。

I looked at using the nm -D command and I see some of the symbols are W, does that mean it will use an existing symbol if it already exists before using the one that was statically built with the library?

不,运行时链接器不会考虑符号的弱点(至少没有 LD_DYNAMIC_WEAK environment variable 我不建议使用)。

关于c++ - 加载具有相同静态链接函数的两个共享库时使用哪个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43622469/

相关文章:

c# - 使用 VC++ MFC 对话从数据库中检索数据

c++ - 如果我改变形状,Pytorch C++ (libtorch) 会输出不同的结果

linux - 从 Windows 到 Linux 的 RPC

c++ - Clang 与 GCC : Error in unevaluated context breaks SFINAE

c++ - 如何在gcc中排除当前路径下的 header

c++ - 如何使用 Arduino/C++ 将整个结构传入和传出函数

c++ - 与类定义相同类型的静态 constexpr 成员(其他详细信息)

linux - runit 会获取孤儿进程吗?

linux - 将 OpenSSL 库链接到程序

linux - y86模拟器(csapp)安装失败