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

时间:2017-04-24 07:28:28

标签: c global-variables shared-libraries extern dlopen

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

int globalvar;

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

extern int globalVar;

现在我的main.c与已编译的global.o(从global.c编译)链接,其中包含打开的代码(使用dlopen)一个共享对象sh.so,它是从sh.c构建的,可以访问globalVar,通过global.h。 虽然,我的可执行文件定义了globalVar(静态链接),但是当我加载动态链接库sh.so时,它表示未定义的globalVar。 如何处理?

2 个答案:

答案 0 :(得分:1)

  

虽然我的可执行文件定义了globalVar(静态链接),但当我加载动态链接库sh.so时,它表示未定义的globalVar。

这是预期的。 ELF二进制文件具有两个符号表:常规符号表和用于动态链接的符号表。您可以这样检查它们:

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

链接器没有将globalVar放入动态符号表的原因是(在链接时)二进制文件之外的任何内容都不需要该符号。

  

如何处理?

有几种方法。

  1. 如果您将-rdynamic添加到链接行,那么您将要求链接器将每个定义的符号导出到动态符号表中。虽然总的来说这是个坏主意,但这是解决问题的最快方法。
  2. 如果您使用黄金链接,则可以使用-Wl,--export-dynamic-symbol=globalVar仅导出globalVar
  3. 您可以使用-Wl,--dynamic-list=globals.txt并将globalVar放入globals.txt文件。
  4. 您可以使用-Wl,--dynamic-list-data导出所有全局数据变量(这仅略高于-rdynamic)。

答案 1 :(得分:-1)

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

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

Antti Haapala的链接How can a shared library (.so) call a function that is implemented in its loader program?显示了如何做到这一点。