step进不去函数主因是未用-g编译导致缺失调试符号,GDB无法映射源码行号,故提示“no line number information”;此时可用stepi按指令单步,配合display/i $pc查看汇编。

step 命令为什么有时进不去函数?
直接用 step(或缩写 s)进不了函数,大概率不是命令错了,而是程序没带调试符号。GDB 依赖编译时生成的调试信息(-g)来映射机器指令和源码行号;没有它,step 就不知道“下一行”对应哪条语句,干脆跳过函数体,直接执行完再停。
典型错误提示是:Single stepping until exit from function xxx, which has no line number information.
- 用
readelf -S ./a.out | grep debug检查可执行文件是否含.debug_*段 - 重新编译必须加
-g:比如gcc -g main.c -o main - 如果用了 Makefile,确认
CFLAGS包含-g,且没被-O2等优化覆盖(高优化可能内联函数,step也进不去)
step 和 next 的关键区别在哪?
step 进入函数,next(或 n)跨过函数——但这个行为只在有调试符号时稳定生效。两者底层逻辑一致:都试图按源码行单步,区别仅在于是否对当前行的函数调用做“深入”。
- 若当前行是
bar(num());,step会先停在num()函数第一行(前提是num有调试信息) -
next则直接执行完num(),停在bar()调用返回后的下一行 - 如果
num()是内联函数或无调试信息,step和next行为可能趋同——都跳过,不进
没调试符号时怎么强行进入函数?
用 stepi(或 si),它不看源码,只按 CPU 指令单步。配合 display/i $pc 实时看反汇编,就能手动“走”进函数内部。
操作示例:
gdb ./a.out (gdb) b bar (gdb) r (gdb) display/i $pc (gdb) stepi # 执行一条指令 (gdb) stepi # 再一条,直到看到 call、jmp 或 push 指令
-
stepi不受调试符号限制,但需要懂一点 x86-64 或 ARM 汇编基础 - 用
info registers查看寄存器值,确认参数是否已载入%rdi、%rsi等 - 想跳过某段汇编?用
jump *0x401150直接跳转(慎用,可能破坏栈)
还有哪些容易被忽略的细节?
真正卡住人的往往不是命令本身,而是环境状态和隐式行为。
-
step在循环/条件分支里可能“跳行”——因为优化导致源码行和指令不一一对应 - 用
set step-mode on可强制step在无调试信息时也尝试单步(但停在汇编层,不是源码) - 如果函数被编译器内联(如加了
inline且开了-O2),step根本看不到该函数存在,得关优化重编译 - 多线程下
step只控制当前线程,其他线程继续跑——别误以为“卡死”了
最常被跳过的事实是:GDB 的单步能力,本质是编译器给的权限,不是调试器自己硬“猜”出来的。没有 -g,就等于交出了源码控制权,剩下的只能靠寄存器和指令硬啃。


















