我使用以下命令从以下C
代码构建了一个共享对象:
gcc -fPIC -shared libx.c -o libx.so
libx.c
extern int printf(const char *, ...);
int libvar = 250;
void libfunc(){
printf("%d,",libvar);
}
然后我使用以下命令将以下C
代码链接到libx.so
库:
gcc -no-pie -lx -L ./ -o main main.c
-no-pie:告诉编译器生成ELF可执行文件而不是共享对象(因为这是我的编译器默认执行的操作)。
的main.c
extern void libfunc();
int main(){
libfunc();
}
现在,在启动程序时,理论上,动态加载程序会将共享库libx.so
映射到正在运行的进程(./main)的地址空间,并将解析符号libfunc
& ; libvar
(更改[{1}}的{{1}}和.got
段中的内容),最终将解析.plt
符号,然后打印PIC
的值这是printf
。
但程序打印出一些奇怪的值:
libvar
我已经进行了长时间的调试,以了解正在发生的事情,但我无法弄明白!
答案 0 :(得分:2)
我改变了一点你的榜样。我的libfunc
现在包含:
void libfunc(){
printf("in libfunc libvar=%d\n",libvar);
}
请注意,gcc
的参数顺序与 lot 相关(并且您对gcc
的参数的顺序错误)。详细了解Invoking GCC。
我用
编译了你的库gcc -fPIC -shared -Wall libx.c -o libx.so
然后我用
编译了你的main.c
gcc -Wall main.c -L. -lx -o main
然后执行失败
./main: error while loading shared libraries: libx.so: cannot open
shared object file: No such file or directory
这是正常的,请参阅ld-linux(8)
要更正该错误,请明确设置LD_LIBRARY_PATH
以包含具有libx.so
的目录(例如.
),例如输入运行程序的相同的终端,例如
export LD_LIBRARY_PATH=.
或通过编译程序
来适当地设置rpath gcc -Wall main.c -Wl,-rpath,. -L. -lx -o main
在这两种情况下我都会
in libfunc libvar=250
运行./main
时预期
BTW,使用strace(1)可以帮助您找到您的错误(不是您显示的代码,而是系统配置错误)。您还可以使用-g
编译库和可执行文件,然后使用gdb
调试器。
答案 1 :(得分:-1)
由于这是一个dinâmica变量,libvar在堆中被不安全地分配,并且可以被操作系统中使用相同内存的其他程序更改。
如果需要更改,最佳做法是每次调用时使用常量或传递值。
答案 2 :(得分:-1)
有人指出图书馆在/lib
,所以我去看看它&我发现我使用的是错误的库,它定义了相同的符号libfunc
& libvar
并且在函数libfunc
中有一些其他printf
导致程序打印错误的值。
因此,从技术上讲,两个库之间的区别在于格式printf
中的字符串参数,我在调试时没有检出。