调试工具总览:GDB、LLDB、strace、ltrace

做系统调试这么多年,我发现自己手头最趁手的家伙,其实就是这四个工具:GDB、LLDB、strace、ltrace。说白了,它们分两大阵营——动态调试器和系统跟踪工具。今天咱们就挨个捋一遍,哪些场景用哪个,怎么用得顺手。

一、动态调试器:GDB 与 LLDB

这两个是给进程“做手术”的。GDB 我用了十年,LLDB 是后来因为 macOS 项目才开始接触。它们都能让你在程序运行时随时停下来,看变量、看堆栈、改内存。

GDB(GNU Debugger)

Linux 下调试 C/C++ 的首选。我个人习惯直接把核心命令记牢:run、break、next、step、backtrace、info locals。说到 backtrace,我记得有一次线上服务半夜崩溃,直接看 crash dump 里的栈帧,就靠 bt 找到了那个空指针。

# 启动调试
gdb ./myapp
(gdb) run
(gdb) bt
(gdb) info registers

避坑指南:我曾经在调试多线程程序时忘了 set follow-fork-mode child,结果子进程一跑就抓不住。嗯,这个选项你得记着。

LLDB(LLVM Debugger)

macOS / iOS 下的调试利器。命令风格和 GDB 很像,但有些名字不一样,比如 thread backtrace 对应 GDB 的 bt。它原生支持 Swift 和 Objective-C,如果你做苹果平台开发,基本离不开它。

lldb ./MyApp
(lldb) run
(lldb) thread backtrace -e true
(lldb) frame variable

你想想看,如果只是要快速看一个 iOS app 的崩溃栈,我一般直接用 lldb attach 到进程,然后 bt 搞定,效率比 Xcode 的 GUI 快不少。

二、系统跟踪工具:strace 与 ltrace

这两个说白了是“偷窥”程序跟操作系统和库的交互。程序死锁、文件打不开、内存越界?先用 strace 看一眼系统调用,再用 ltrace 看库函数,定位速度直接翻倍。

strace(系统调用跟踪)

它跟踪程序发起的每一个系统调用——open、read、write、mmap……我当年排查一个“启动慢”的问题,用 strace 发现程序反复打开同一个配置文件三次,后来一查是初始化顺序写错了。

strace -o trace.log ./myapp
strace -p 12345 -f   # 跟踪子进程

⚠️ 注意:strace 输出量极大,我建议先用 -c 做个统计,再针对高频调用加 -e 过滤。

strace -c ./myapp   # 打印系统调用计数
strace -e trace=open,read ./myapp   # 只看 open 和 read

避坑指南:我曾经用 strace 跟踪一个守护进程,没加 -f,结果子进程创建后一路没被跟踪,白忙活半小时。记住:多进程程序一定要 -f。

ltrace(库调用跟踪)

它跟踪的是动态库函数调用,像 malloc、printf、strlen 这些。如果 strace 没发现系统调用异常,那问题很可能发生在用户态库函数里。

ltrace -o lib.log ./myapp
ltrace -e malloc+free ./myapp   # 只看内存分配相关

举个例子:程序跑着跑着内存暴涨,用 strace 看 brk 并不频繁,但 ltrace 里的 malloc 次数却飙升。嗯,那肯定是调用层的问题,比如忘记释放了。

三、工具对比速查表

工具领域典型场景调试语言
GDB动态调试断点、堆栈、寄存器C/C++、Fortran
LLDB动态调试macOS/iOS 崩溃分析C/C++、Swift、ObjC
strace系统调用文件 I/O、网络、进程创建所有用户态程序
ltrace库函数调用内存泄漏、库调用顺序动态链接的程序

实战口诀:先 strace 查系统调用,再 ltrace 查库函数,最后 GDB / LLDB 下断点打桩。三层下来,90% 的崩溃都能定位。

小技巧:GDB 的 catch syscall 可以像 strace 一样抓系统调用,但调试功能更强。LLDB 里对应的命令是 breakpoint set -n start -s libsystem_kernel.dylib。

四、工具选择决策流程

我平时遇到问题,先问自己:

  1. 程序崩了,但不知道在哪? → 直接 GDB/LLDB 加载 core dump,bt 看栈。
  2. 卡住不动,怀疑死锁? → strace 看进程卡在哪个系统调用上(比如 futex 等锁)。
  3. 内存越来越大,怀疑泄漏? → ltrace 盯 malloc/free 次数差异。
  4. 启动巨慢,想优化? → strace -c 统计系统调用耗时。

记住一个原则:能用 strace / ltrace 的场合,不要急着上 GDB。因为跟踪工具不会打断程序运行,适合线上应急。但需要修 bug 时,GDB 的断点调试无可替代。

调试工具总览结构图 调试工具 动态调试器 系统跟踪工具 GDB LLDB strace ltrace 左:动态调试器 — 断点、单步、堆栈分析 右:系统跟踪工具 — 系统调用与库函数追踪

这张结构图帮你快速定位:遇到崩溃问题,先判断是用户态逻辑问题(上动态调试器)还是系统交互问题(上系统跟踪工具)。两个阵营配合使用,效率最高。