我在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。 如何处理?
答案 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
放入动态符号表的原因是(在链接时)二进制文件之外的任何内容都不需要该符号。
如何处理?
有几种方法。
-rdynamic
添加到链接行,那么您将要求链接器将每个定义的符号导出到动态符号表中。虽然总的来说这是个坏主意,但这是解决问题的最快方法。-Wl,--export-dynamic-symbol=globalVar
仅导出globalVar
-Wl,--dynamic-list=globals.txt
并将globalVar
放入globals.txt
文件。-Wl,--dynamic-list-data
导出所有全局数据变量(这仅略高于-rdynamic
)。答案 1 :(得分:-1)
更多作为解释而不是解决方案(我不是Linux共享库的专家),在global.o
和sh.so
中,只知道他们自己单位的变量和函数的地址
因此,要让共享库知道可执行文件中全局变量的位置,您必须告诉动态库在哪里找到它,即它的地址是什么。同样,当您想要在动态库中调用函数时,您必须请求库中的地址。
Antti Haapala的链接How can a shared library (.so) call a function that is implemented in its loader program?显示了如何做到这一点。