为什么这个动态加载的库不能访问加载程序的全局变量?

时间:2010-12-20 04:35:25

标签: c global-variables dynamic-linking

首先,我看过this(< - 一个链接),但它无效。我正在使用OS X.

交流转换器:

#include <stdio.h>
#include <dlfcn.h>

int global_var = 0x9262;

int main(void) {
  void *handle = dlopen("libb.so", RTLD_LAZY);
  void (*func)(void);
  char *err;
  if (handle == NULL) {
    fprintf(stderr, "%s\n", dlerror());
    return 1;
  }
  func = dlsym(handle, "func");
  if ((err = dlerror()) != NULL) {
    fprintf(stderr, "%s\n", err);
    return 2;
  }
  global_var = 0x9263;
  func();
  return -dlclose(handle) * 3;
}

b.c:

#include <stdio.h>

extern int global_var;

void func(void) {
  printf("0x%x\n", global_var);
}

编译并运行:

$ gcc -shared -rdynamic -fpic -o liba.so a.c
$ gcc -shared -fpic -o libb.so -L. -la b.c
$ gcc -fpic -o a a.c
$ ./a
0x9262

为什么不打印0x9263?我已经尝试了很多编译器标志的组合,但没有一个能够工作。

2 个答案:

答案 0 :(得分:3)

您已创建了global_var的两个实例。一个在liba.so中定义,这是b.c引用的那个。

另一个在a中定义,这是您的main()函数引用的那个。

如果您希望main函数引用liba.so中的变量,它需要extern声明它而不是定义,并且它需要链接到该库本身。

答案 1 :(得分:0)

有趣的问题。 答案也很有趣。

正如他在回复中提到的那样,你创建了两个global_var的定义。

要完成您要实现的目标,您必须确保从主可执行文件解析global_var。为此,您必须创建一个导入文件,该文件指出,global_var是从主可执行文件导入的。在导入文件中,您应该使用#!。对此。

然后在创建库时使用此导入文件。

同时在编译主二进制文件时,请确保导出global_var变量。使用适当的编译器标志。

在我的unix盒子上,我尝试了这个并且它可以工作。

# cat imp.imp
 #!.

 global_var

cc main.c -bexpall
cc  lib.c -bM:SRE -bnoentry -bI:./imp.imp -bexpall -o libb.so