gcc -v 可显示完整编译链接过程,包括调用工具、参数、搜索路径及库加载尝试;关键链接信息位于输出末尾,以 collect2 或 ld 开头,含 attempt to open 行,配合 grep "attempt\|ld\|collect2" 可精准定位。

gcc -v 能看到完整链接过程,但输出太杂
直接加 -v 是最常用也最可靠的手段。它会把整个编译+链接链路里调用的每个工具、传给它们的参数、搜索路径、链接库顺序都打印出来——包括 ld 实际执行时加载了哪些 .a 或 .so 文件。
常见错误现象:你加了 -L/path/to/lib 却报 /usr/bin/ld: cannot find -lxxx,光看报错不知道 ld 到底搜了哪些目录。这时候 gcc -v main.cpp -lxxx 一跑,就能在输出末尾看到一长串 search path 和最终尝试打开的库文件名。
-
-v输出里关键段落通常以collect2或ld开头,接着是attempt to open行,逐个列出它尝试加载的库路径 - 如果用了
-static,你会看到它优先找libxxx.a;没加则先找libxxx.so - 输出中夹杂大量预处理和编译信息,真正链接部分集中在最后 1/4,建议配合
grep "attempt\|ld\|collect2"过滤
gcc -Wl,--verbose 只显示链接器内部行为
-Wl,--verbose 把 --verbose 参数透传给 ld,比 -v 更聚焦于链接阶段本身,不掺杂 cpp 或 cc1 的日志。
使用场景:你想确认某个符号(比如 std::string::append)最终是从哪个库解析来的,或者想看链接器是否启用了 --as-needed 等策略。
立即学习“C++免费学习笔记(深入)”;
- 输出里会列出所有输入目标文件(
main.o、libstdc++.a等)及其节(.text、.data)如何合并 - 每行
ld: warning: cannot find entry symbol _start这类提示说明链接器没找到入口,常因错用-c或漏传-shared - 注意:这个选项只对链接生效,如果你没到链接阶段(比如只用
-c),它不会有任何输出
ldd 查看已生成可执行文件的动态依赖
ldd 不是编译时选项,但它能反向验证链接结果是否符合预期——尤其当你怀疑运行时报 undefined symbol 或 version mismatch 时。
典型误操作:你以为加了 -lboost_system 就一定链接进去了,结果 ldd ./a.out | grep boost 发现根本没列出来,说明链接阶段根本没成功绑定。
-
ldd显示的是运行时实际加载的共享库路径,不是编译时指定的路径 - 若某库显示
not found,说明该库不在LD_LIBRARY_PATH或系统默认路径(如/usr/lib)中 - 对静态链接的二进制(
gcc -static生成),ldd会提示not a dynamic executable
为什么不用 gcc -###?
gcc -### 看起来像“更详细版本的 -v”,但它实际只展开命令行参数,不执行任何步骤,也不触发 ld 的真实行为。它告诉你“GCC 打算调用什么”,但不告诉你“ld 实际打开了哪些文件”。
容易踩的坑:新手看到 -### 输出里有 ld ... -lxxx 就以为链接成功了,结果运行时报错才发现库根本没被找到——因为 -### 不做任何文件存在性检查,也不启动 ld。
真正要调试链接问题,必须让 GCC 走完链接阶段,也就是去掉 -c、-S、-E 这些跳过链接的选项,再配合 -v 或 -Wl,--verbose。
链接过程里最易被忽略的点:路径拼接逻辑(-L 后跟的路径是否以 / 结尾)、库名与 -l 参数的映射规则(-lfoo → libfoo.so 或 libfoo.a)、以及 ld 默认启用 --as-needed 导致某些库被静默丢弃。


















