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

问题描述:

首先,我看到了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?我已经尝试了许多编译器标志的组合,并且它们都不起作用。

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

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

如果你想要你的主函数引用liba.so中的变量,它需要一个extern声明它而不是一个定义,它需要链接到该库本身。

+0

+1正确(还有一些字符) – slezica 2010-12-20 04:58:22

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

正如他在回复中提到的caf,你已经创建了两个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 
+0

#未能在帖子中正确显示 – cexpert 2010-12-20 06:55:18