我在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.SH.SO时,它说UNDEDENDEND GLOBALVAR。如何处理?
,尽管我的可执行文件具有对globalvar(静态链接(的定义,但是当我加载动态链接的库SH.SO时,它说UNDEDENDING globalvar。
这是预期的。精灵二进制文件具有两个符号表:一个常规的符号表,一个用于动态链接的常规符号表。您可以这样检查:
nm a.out | grep globalVar # expected: address D globalVar
nm -D a.out | grep globalVar # expected: no output
链接器不会将globalVar
放入动态符号表中的原因是(在链接时间(二进制符号之外的任何内容。
如何处理?
有几种方法。
- 如果将
-rdynamic
添加到链接行中,您将要求链接器导出每个定义的符号到动态符号表中。总的来说,这是一个坏主意,但这是解决您的问题的最快方法。 - 如果您使用黄金链接,则可以使用
-Wl,--export-dynamic-symbol=globalVar
仅导出globalVar
- 您可以使用
-Wl,--dynamic-list=globals.txt
并将globalVar
放入globals.txt
文件中。 - 您可以使用
-Wl,--dynamic-list-data
导出所有全局数据变量(这仅比-rdynamic
略好(。
作为解释,而不是解决方案(我不是Linux共享库中的专家(,在global.o
和sh.so
中,只有其单元的变量和函数的地址是已知的。
因此,要让共享库知道可执行文件中全局变量的位置,您必须 tell 动态库在哪里可以找到它,即其地址是什么。以同样的方式,当您要在动态库中调用函数时,必须请求库的地址。
Antti Haapala的链接,共享库(.SO(如何调用其加载程序程序中实现的函数?显示如何进行。