﻿# ldd —— 查看可执行文件/库的动态库依赖

`ldd` 列出一个动态链接程序运行时需要加载哪些共享库（`.so`），以及它们被解析到的实际路径。排查"启动报 `error while loading shared libraries` / `cannot open shared object`"时的首选。

## 数据来源

- **来源对象**：先读 ELF 的 `.dynamic` 节拿到 `NEEDED` 直接依赖，再**调用动态链接器 `ld.so`** 实际做一遍符号解析，递归展开全部依赖及其解析到的路径。
- **采集方式**：不是纯读文件——它借助 ld.so 走一遍真实的加载/查找流程（受 `LD_LIBRARY_PATH`、`ld.so.cache` 等影响）。
- **由此决定的特性**：⚠️ 因为会**调用 ld.so 加载程序**，对**不可信二进制不安全**（某些情况下可能触发执行）；只想安全地看直接依赖，改用纯静态读的 `readelf -d`（见正文）。

```bash
# glibc 自带，无需额外安装
ldd <file>
```
## 一、用法与输出

```bash
$ ldd ./cpu_demo
        linux-vdso.so.1 (0x00007fff...)             # 内核提供的虚拟 so，不是真实文件
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f...)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f...)
        /lib64/ld-linux-x86-64.so.2 (0x00007f...)   # 动态链接器本身
```
每行：`需要的库名 => 解析到的实际路径 (加载地址)`。

- `=> not found` → **缺库**，就是启动失败的原因，需装库或配 `LD_LIBRARY_PATH`。
- `linux-vdso.so.1` 没有路径是正常的（内核映射的虚拟库）。

## 二、`not found` 排查

```bash
ldd ./myapp | grep 'not found'         # 找出缺哪些库
```
解决思路：
1. 装缺的库（`apt install libxxx` / `yum install xxx`）。
2. 库在非标准路径 → 加到 `/etc/ld.so.conf.d/xxx.conf` 后 `ldconfig`，或临时 `export LD_LIBRARY_PATH=/opt/mylib:$LD_LIBRARY_PATH`。
3. 版本号对不上（要 `libfoo.so.2` 只有 `libfoo.so.3`）→ 装对应版本或建软链（谨慎）。

```bash
ldconfig -p | grep libstdc++           # 查系统已注册的库缓存里有没有它
```
## 三、⚠️ 安全警告

**别对不信任的程序跑 `ldd`**。`ldd` 的部分实现是**真的把程序加载起来**来解析依赖的，等于执行了它。分析来路不明的二进制时，改用不执行程序的安全方式：

```bash
readelf -d ./suspicious | grep NEEDED   # 只读 ELF 的 .dynamic 节，不执行程序（推荐）
objdump -p ./suspicious | grep NEEDED   # 同样安全
```
`readelf -d` 只列**直接依赖**（NEEDED 项）；`ldd` 列**递归的全部依赖**（依赖的库还依赖谁）。想看直接依赖且安全，用 readelf。

## 四、结合本仓库

```bash
make
ldd ./cpu_demo                          # 应看到 libstdc++、libc、libpthread（用了 std::thread）
readelf -d ./cpu_demo | grep NEEDED     # 安全版：只看直接依赖
```
> cpu_demo 用了 `std::thread`，所以依赖 `libpthread`（新版 glibc 已把 pthread 并入 libc，可能看不到独立的 libpthread）。Makefile 里 `-pthread` 就是为链接它。

## 五、相关

- 静态链接的程序（`-static`）`ldd` 会显示 `not a dynamic executable` —— 没有外部依赖。
- 看某个 `.so` 又依赖谁：`ldd libfoo.so`。
- 运行时到底加载了哪些库、从哪加载：`LD_DEBUG=libs ./cpu_demo` 会打印动态链接器的详细查找过程。

