ldd可查看.so文件的动态依赖,输出“not found”表示库不可见;更可靠的方式是readelf -d lib.so | grep NEEDED读取硬编码的DT_NEEDED条目,不受环境干扰。

用 ldd 查看动态库本身的依赖
动态库(.so 文件)自己也可能依赖其他库,比如 libm.so.6、libc.so.6,甚至其他自定义的 .so。直接对 .so 文件运行 ldd 就能看清它要什么:
ldd libmylib.so
输出中如果某行显示 not found,说明该库在当前系统路径下不可见——不是你漏编译了,而是运行时找不到它。
常见陷阱:
-
ldd会尝试“模拟加载”,所以若libmylib.so依赖另一个未安装的自定义库(如libhelper.so),它不会报错退出,但会标not found;此时不能靠返回值判断成败,得人工扫输出 - 若
libmylib.so是用-fPIC编译但没加-shared,生成的是普通目标文件(.o),ldd会报错:not a dynamic executable—— 这说明根本不是合法的.so
用 readelf -d 看 ELF 动态段里的真实依赖项
ldd 是用户友好的封装,但有时它被环境变量(如 LD_LIBRARY_PATH)干扰,或因权限问题无法读取某些路径。更底层、更可靠的方式是直接读取 ELF 结构:
readelf -d libmylib.so | grep NEEDED
这条命令只输出 DT_NEEDED 条目,也就是编译链接时硬编码进来的依赖库名(如 libm.so.6),不走搜索逻辑,不受环境影响。
注意点:
- 输出的是库的 soname(如
libc.so.6),不是文件路径,也不反映是否实际存在 - 如果看到
libgcc_s.so.1或libstdc++.so.6,说明你的库用了 C++ 异常或 RTTI,且没静态链接这些运行时支持库 - 空输出?那这个
.so可能是纯 C 实现、只依赖libc(而libc属于“必须存在”的隐式依赖,通常不显式写入DT_NEEDED)
为什么 nm -D 不能代替依赖检查
nm -D libmylib.so 显示的是该库**导出的符号**(即它提供给别人的函数/变量),比如 get_random_number。它完全不告诉你这个库自己需要什么。
容易混淆的场景:
- 你用
nm -D确认了函数已导出,但程序仍报undefined symbol—— 那问题不在导出,而在调用方链接时没找到这个库,或运行时加载失败 -
nm -D不显示内部调用的第三方函数(如sin、malloc),那些依赖只能靠ldd或readelf -d暴露
Clang 生成的 .so 特别要注意 ABI 和链接器行为
Clang 默认使用 lld(LLVM 自带链接器),而 ldd 和 readelf 对 lld 产出的 .so 完全兼容,但以下细节会影响依赖呈现:
- Clang 编译时若没加
-fPIC,-shared会失败或静默降级(取决于版本),导致生成的不是真正位置无关的.so;这种文件可能被ldd拒绝识别 - Clang 默认启用
-stdlib=libc++(而非libstdc++),所以依赖可能是libc++.so.1,而不是常见的libstdc++.so.6;部署时别只装 GCC 工具链而漏掉 libc++ 运行时 - 若用
-Wl,-rpath,$ORIGIN嵌入了运行时搜索路径,readelf -d里能看到DT_RUNPATH,但ldd不会体现这个路径是否生效——得实际跑起来或用LD_DEBUG=libs ./your_app验证
依赖检查不是一次性的动作。真正关键的,是搞清每个 not found 是路径缺失、命名不匹配,还是 ABI/stdlib 不一致——这三类问题的修复方式完全不同。


















