编译Linux Foundation视频代码失败:共享库加载问题求助
问题场景
我观看SUSE的Shung-Hsi Yu发布的《What Is an ABI, and Why Should You Care?》视频时,跟着视频中的代码和编译步骤操作,遇到了共享库加载失败的问题。
代码文件
geo.h:
struct point { long x; long y; }; long x_square(struct point *);
geo.c:
#include <geo.h> long x_square(struct point *p) { return p->x * p->x; }
main.c:
#include <geo.h> long arr[] = {0, 1, 2, 3, 4}; int main(void) { struct point p = { .x = 2, .y = 1, }; printf("Calculating\n"); long x2 = x_square(&p); return arr[x2]; }
编译命令
我使用的编译命令和视频一致,仅添加了-std=c90参数以在不包含stdio.h的情况下编译printf:
gcc -I$(pwd) -shared -o ./libgeo.so geo.c -std=c90 gcc -I$(pwd) -o ./main libgeo.so main.c -std=c90
错误信息
运行./main; echo $?时出现如下错误:
./main: error while loading shared libraries: libgeo.so: cannot open shared object file: No such file or directory 127
共享库libgeo.so与可执行文件main在同一目录下,但无法加载,而视频中的演示则能正常运行。我的CPU为x86_64,操作系统是Fedora Linux。
原因分析
Linux的动态链接器默认不会将当前目录纳入共享库搜索路径,这是多数现代发行版(包括Fedora)的安全默认设置——防止恶意库文件被误加载。视频中的演示能正常运行,大概率是因为编译时添加了rpath参数,或者运行时临时设置了环境变量,只是这些步骤没在视频中明确展示。
解决办法
方法1:临时设置环境变量
运行时通过LD_LIBRARY_PATH告诉动态链接器搜索当前目录,这是临时生效的方案:
LD_LIBRARY_PATH=. ./main; echo $?
方法2:编译时添加rpath参数
修改编译main的命令,添加-Wl,-rpath='$ORIGIN'参数,让可执行文件加载时自动在自身所在目录查找共享库,这是长期生效的方案:
gcc -I$(pwd) -o ./main libgeo.so main.c -std=c90 -Wl,-rpath='$ORIGIN'
其中$ORIGIN是动态链接器的特殊变量,代表可执行文件所在的绝对路径,这样即使把main和libgeo.so一起移动到其他目录,也能正常加载。
方法3:将库文件放到系统默认路径(不推荐)
把libgeo.so复制到系统默认的共享库目录(如/usr/lib64/),然后运行ldconfig更新缓存:
sudo cp ./libgeo.so /usr/lib64/ sudo ldconfig
这种方法会污染系统库目录,仅适合需要全局使用的库文件,不推荐用于测试或临时项目。
内容的提问来源于stack exchange,提问作者KeshawT

