共享对象中的符号

symbols in shared objects

本文关键字:符号 对象 共享      更新时间:2023-10-16

我的场景是:

  • 框架工作静态库 - libFramework.a
  • 使用该框架的共享对象 - mySharedObj.so
  • 使用两个库的可执行文件 - myExe.elf

我正在分别编译某某和精灵。 有时框架有一个新版本,我只想更新 so 或只更新 elf(没关系( 但是当我运行应用程序(带有调试(时,我看到 so 正在使用 elf 框架库 在精灵下运行时,我如何"强制"所以使用自己的框架实例

顺便说一句,如果碰巧 so 和 elf 都有一个同名的类(如果不使用命名空间等(,我也有同样的问题。 所以是使用精灵类。

可能发生的事情是libFramework.a正在公开动态符号。当你启动myExe.elf时,它会从自身(或它自己的libFramework.a副本,如果你想这样看它(解析这些动态符号。

加载 mySharedObj.so 时,它会再次解析所有这些符号,并在 myExe.elf 而不是 mySharedObj.so 中找到这些符号,因为它重用了上一个解析的结果。您可以通过运行 myExe.elf LD_DEBUG=all 来确认这一点,例如LD_DEBUG=all myExe.elf.

为了阻止这种情况发生,您需要防止libFramework.a导出任何动态符号。您可以使用编译器标志-fvisibility=hidden将默认值更改为隐藏的符号,然后确保您的符号不会通过源代码中的属性再次可见,例如__attribute__ ((visibility ("default")))或通过推动和弹出可见性#pragma GCC visibility push(default)#pragma GCC visibility pop.您还可以使用 nm 查看哪些符号显示为动态符号。

出于性能原因,也值得检查此类内容。如果所有符号都是动态的,则运行时动态链接器必须执行更多工作,因此程序的加载时间将更长。编译器还可以生成更好的代码,因为它不必输入代码即可动态调用函数。链接器可以更好地消除死代码等。有很多胜利。