【问题标题】:Handling global variables in shared object处理共享对象中的全局变量
【发布时间】:2017-09-20 18:50:49
【问题描述】:

我在 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 时,它显示 undefined globalVar。 如何处理?

【问题讨论】:

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


【解决方案1】:

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

这是意料之中的。一个 ELF 二进制文件有 两个 符号表:一个常规的和一个用于动态链接的。你可以像这样检查它们:

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

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

如何处理?

有几种方法。

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

【讨论】:

    【解决方案2】:

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

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

    Antti Haapala 的链接How can a shared library (.so) call a function that is implemented in its loader program? 显示了如何执行此操作。

    【讨论】:

    • 这个解释多半是错误的。当然,您可以在主可执行文件中调用open,并在libc.so 中找到open 的定义 不做任何特殊操作。
    • @Employed Russion,也许你可以找到定义(告诉我怎么做???)但你不能访问它,因为你不知道它的地址。您将必须做一些特别的事情,无论是您自己、库还是编译器。
    • 您忘记了链接器和动态加载器,它们共同使这一切正常工作。无论如何,您的解释意味着程序员必须做一些“找到定义”的事情,显然情况并非如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-19
    • 1970-01-01
    • 2019-01-15
    • 2016-11-14
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多