处理共享对象中的全局变量

Handling global variables in shared object

我在 global.c 文件中定义了一些全局变量,如下所示:

int globalvar;

我有一个头文件 global.h 将这个变量声明为 extern

extern int globalVar;

现在我有 main.c 与已编译的 global.o(从 global.c 编译)链接,具有打开(使用 dlopen)共享对象 sh.so 的代码从 sh.c 构建,通过 global.h 访问 globalVar。 尽管我的可执行文件具有 globalVar 的定义(静态链接),但当我加载动态链接库 sh.so 时,它显示未定义的 globalVar。 如何处理?

更多的是解释而不是解决方案(我不是 Linux 共享库的专家),在 global.osh.so 中只有变量和函数的地址他们自己的单位是已知的。

因此,要让共享库知道全局变量在您的可执行文件中的位置,您必须告诉动态库在哪里可以找到它,即它的地址是什么。同理,当你想调用动态库中的函数时,你必须请求库的地址。

A​​ntti Haapala How can a shared library (.so) call a function that is implemented in its loader program? 的 link 展示了如何执行此操作。

Although, my executable has definition of globalVar (statically linked), when I load the dynamically linked library sh.so, it says undefined globalVar.

这是意料之中的。一个 ELF 二进制文件有 两个 符号 tables:一个是常规的,一个是用于动态 linking 的。您可以像这样检查它们:

 nm    a.out | grep globalVar  # expected: address D globalVar
 nm -D a.out | grep globalVar  # expected: no output

linker 没有将 globalVar 放入动态符号 table 的原因是(在 link 时间)二进制文件之外的任何东西都不需要该符号.

How to handle this?

有几种方法。

  1. 如果您将 -rdynamic 添加到 link 行,您将要求 linker 将 每个 定义的符号导出到动态符号 table。虽然总的来说这是个坏主意,但这是解决您问题的最快方法。
  2. 如果您使用金币 link,您可以使用 -Wl,--export-dynamic-symbol=globalVar 仅导出 globalVar
  3. 您可以使用 -Wl,--dynamic-list=globals.txt 并将 globalVar 放入 globals.txt 文件。
  4. 您可以使用-Wl,--dynamic-list-data导出所有全局数据变量(这只比-rdynamic稍微好一点)。