关于 C/C++的共享库问题

2021-03-13 15:27:55 +08:00
 xiaopanzi

昨天读到一篇介绍共享库问题的博客,很受启发。地址: https://amir.rachum.com/blog/2016/09/17/shared-libraries/。

文中的例子简述如下:同一目录下,有main.ccp, random.hrandom.cpp,将random.cpp打包成 so 文件,再让main.cpp和该 so 文件链接得到可执行文件main

但是有个疑问,在该博客中通过clang++ -o main main.o -lrandom -L.之后,无法直接运行该可执行文件,报的错误是:

/main: error while loading shared libraries: librandom.so: cannot open shared object file: No such file or directory

但是经过我测试(分别在 Ubuntu 下的 g++ 9.3 和 Mac OS 下的 clang++ 12.0),我可以直接运行该可执行文件,通过ldd命令也可看出 librandom.so 文件是能够被找到的。

linux-vdso.so.1 (0x00007ffe279d2000) librandom.so (0x00007f7776fca000) libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f7776dcd000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7776bdb000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7776a8c000) /lib64/ld-linux-x86-64.so.2 (0x00007f7776fd6000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f7776a71000)

那是不是意味着,从某个版本开始,g++/clang++能够自动查找当前目录下的 so 文件?如果是,如何确认 g++/clang++的可搜索的路径包括当前目前(即.)?

2577 次点击
所在节点    C++
16 条回复
msg7086
2021-03-13 15:40:32 +08:00
g++ 8.3 无法复现。

# ldd main
linux-vdso.so.1 (0x00007ffe86d29000)
librandom.so => not found
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f6aeaa49000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f6aea8c6000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f6aea8ac000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6aea6eb000)
/lib64/ld-linux-x86-64.so.2 (0x00007f6aeabe3000)
xiaopanzi
2021-03-13 15:47:57 +08:00
@msg7086 那确实很有可能新版本的 g++新增了在当前路径查找 so 的功能。但我想知道如何验证这个猜想。比如: https://stackoverflow.com/questions/9922949/how-to-print-the-ldlinker-search-path 中打印搜索 lib 的目录,并没有"."。
xiaopanzi
2021-03-13 15:59:56 +08:00
哪位朋友用 g++ 9.3+试试?
zhongrs232
2021-03-13 16:19:37 +08:00
@xiaopanzi Ubuntu20.04 ,gcc/g++ 9.3.0,无法复现,必须指定-Wl,-rpath=.
thedrwu
2021-03-13 16:35:24 +08:00
没设 relpath ?
Jirajine
2021-03-13 16:37:54 +08:00
这个和编译器无关吧,寻找动态库是动态链接器( ld-xxx-arch.so )干的。检查一下你的 ldconfig 。
xiaopanzi
2021-03-13 16:37:57 +08:00
@zhongrs232 奇怪了?如何解释这个相同 g++版本的不同行为?
zhongrs232
2021-03-13 16:39:07 +08:00
@xiaopanzi 你是不是还设置了 LD_LIBRARY_PATH=. ?
xiaopanzi
2021-03-13 16:45:32 +08:00
@Jirajine 那个只是更新 ld.so.conf,但里面并无异常。我当前目录不在其搜索路径。
xiaopanzi
2021-03-13 16:58:15 +08:00
@zhongrs232 多谢提醒。我之前在 LD_LIBRARY_PATH 里面设置的是 export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/cuda-11.2/lib64 。最后的结果就是`:/usr/local/cuda-11.2/lib64`,这个`:`有可能相当于把`.`包含进去了?
neoblackcap
2021-03-13 17:02:18 +08:00
我没记错的话,好像是不同编译器的默认行为(rpath)会不一样。
反正我都是直接指定 LD_LIBRARY_PATH,没有必要去赌这个
xiaopanzi
2021-03-13 17:06:43 +08:00
@neoblackcap 嗯。基本破案了,应该是我之前 LD_LIBRARY_PATH 中的:导致的。之前看到一些说法是 LD_LIBRARY_PATH 建议不要设置,比如: https://www.ituring.com.cn/article/22101
neoblackcap
2021-03-13 17:33:02 +08:00
@xiaopanzi
恰恰相反,LD_LIBRARY_PATH 是一个很常用的做法,Firefox 等软件都有用。你要弄一个绿色版的软件,你不指定动态库路径,别人怎么用? Stackoverflow 上面有讨论过这个问题
wzzzx
2021-03-13 22:48:31 +08:00
把 LD_LIBRARY_PATHd 的.取消掉再跑跑?
codehz
2021-03-14 05:25:35 +08:00
@neoblackcap 并不常见,这个用法多数是一种 hack,而且一定要严格限定范围,最好直接只针对特定 desktop 文件。。全局设置肯定炸。。。
绿色版软件这种说法,在 linux 下就很奇怪,因为除了动态库本身之外还有很多因素会干掉你的兼容性(比如 glibc 版本),分发的时候一般都是采用 1. 打包成 deb,rpm,2. 使用 snap,flathub,appimage 等容器机制
(而且非要 hack 也推荐直接用 rpath 加 $ORIGIN 特殊关键字来实现(见 nix patchelf )不方便改二进制的时候才会考虑使用环境变量。)
环境变量会继承,设置成这种相当于自己引入 windows 想改改不掉的 dll 当前目录查找机制(造成了多少安全漏洞,尤其是在下载目录,不小心下载一个恶意动态库你一执行别的程序就直接被黑了)(这种漏洞已经被广泛利用)
zwzmzd
2021-03-14 15:14:40 +08:00
env LD_DEBUG=files 启动指令

可以看到加载 so 的过程

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/761298

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX