nm -u 是查看 .o 文件未定义符号的核心命令,直接列出所有标记为 u 的引用符号,反映编译器生成的外部依赖;不加 -u 则默认显示全部符号,干扰判断。

nm 查看 .o 文件未定义符号的核心命令
直接用 nm -u 就能列出所有未定义符号,这是最常用也最可靠的手段。注意:必须加 -u(或等价的 --undefined-only),否则默认会显示所有符号(包括已定义的),信息太多反而干扰判断。
典型用法:
nm -u main.o
输出类似:
U printf
U malloc
U my_helper_function
其中 U 表示 “undefined”,即该符号在当前 .o 中被引用但未定义,需由链接器从其他目标文件或库中解析。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
为什么有时 nm -u 什么也不输出?
常见原因不是命令写错,而是符号根本没被引用,或者被优化掉了:
- 函数/变量声明了但没被调用或使用 → 编译器可能完全不生成对该符号的引用
- 启用了
-O2或更高优化级 → 内联、死代码消除可能导致符号引用消失 - 符号被
static修饰 → 属于本文件作用域,不会出现在未定义列表中 - 用了
__attribute__((weak))且未提供定义 →nm -u通常仍会显示为U,但链接时允许缺失;个别旧版 binutils 可能行为不一致
和 readelf -d / objdump -T 的区别在哪
nm -u 看的是符号表(.symtab)中标记为未定义的条目,反映编译器生成的引用意图;而:
-
readelf -d xxx.o对.o文件基本无意义 ——-d是查动态段,只存在于可执行文件或共享库中 -
objdump -T xxx.o同样无效 ——-T列动态符号表,.o没有动态符号表 - 真正可替代的只有
readelf -s xxx.o | grep "UND ",但输出格式更冗长,不如nm -u直观
实际调试时容易忽略的细节
未定义符号不等于链接错误,它只是中间状态。真正要关注的是链接阶段是否能全部解析:
-
nm -u输出的符号,如果最终链接失败,错误信息里出现的undefined reference to 'xxx'一定在其中 - C++ 名字修饰(name mangling)会让符号名看起来像乱码,比如
_ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKSt7vectorIS4_T2_E,这是正常的,可用c++filt解析:echo "_ZStls..." | c++filt - 静态库(
.a)里的.o需要先解包(ar x libxxx.a)再对单个.o运行nm -u,不能直接对.a执行
符号未定义本身不是 bug,它是链接模型的正常一环;真正的问题往往藏在“为什么该有的定义没被链接进来”。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










