gpt4 book ai didi

c - 全局变量、共享库和 -fPIC 效果

转载 作者:太空狗 更新时间:2023-10-29 16:38:48 45 4
gpt4 key购买 nike

我制作了一段代码,其中包含一个动态库(lib.c)和一个主要可执行文件(main.c)。在这两个文件中,我都定义了一个名为:int global 的全局变量。不是很聪明,但这不是问题所在。

当我编译动态库时,-fPIC 选项似乎是必需的:

gcc lib.c -fPIC -shared -o lib.so

否则我得到:

/usr/bin/ld: /tmp/ccpUvIPj.o: relocation R_X86_64_32 against '.rodata' can not be used when making a shared object; recompile with -fPIC

当我编译可执行文件时它不是。

gcc main.c -fPIC -ldl
gcc main.c -ldl

两者都有效,但有不同的行为我无法解释,你可以吗? :

加上-fPIC,main.c中的global和lib.c中的global是同一个变量:

global main: 23 (0x601050)
global lib: 23 (0x601050)

没有 -fPIC,lib.c 中的全局与 main.c 中的全局不相关:

global main: 23 (0x601048)
global lib: 0 (0x7f7742e64028)

这是来源:

库文件

#include <stdio.h>
#include <stdlib.h>

int global;

int f_one() {

printf("global lib: %d (%p)\n", global, &global);

return EXIT_SUCCESS;
}

主.c

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

void * handle;
int global;

int main() {

int q = 7;

int (* f_one_p)(int a) = NULL;

global = 23;

handle = dlopen("./lib.so", RTLD_NOW);

if (handle == 0) {
return EXIT_FAILURE;
}

f_one_p = dlsym(handle, "f_one");

printf("global main: %d (%p)\n", global, &global);

f_one_p(q);

return EXIT_SUCCESS;

}

gcc --version: gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2

uname -a: Linux xxx 2.6.38-11-generic#48-Ubuntu SMP Fri Jul 29 19:02:55 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux

编辑:代码在 SUN/sparc 和 x86/Linux 架构下测试,具有相同类型的意外共享全局变量(使用 -fPIC)。

最佳答案

当您使用-fPIC 进行编译时,相关对象将使用全局偏移表 确定全局符号的地址。虽然当部分代码是 -fPIC 而部分不是时会发生什么是您的 int global 之一将使用此表来确定地址,而另一个一部分不是。

如果您有两个共享对象与 -fPIC 链接,但您的主程序没有,那么您仍然会有两个地址用于 int global,一个使用全局偏移表一个是非 PIC 代码的本地代码。

有一个 really great discussion on PIC vs pic vs non PIC如果您想进一步阅读。

关于c - 全局变量、共享库和 -fPIC 效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7298186/

45 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com