info threads 命令用于查看GDB中所有线程的ID、状态、函数调用位置及当前活跃标记(*),是多线程调试首要命令;它不反映执行顺序,仅按内部ID排列,配合thread apply all bt可一次性获取全部线程调用栈,结合thread <n>切换后用info registers和bt full深入分析崩溃上下文。

info threads 显示所有线程快照
core 文件里存的是进程崩溃瞬间所有线程的寄存器、栈帧和状态快照。info threads 是进入 GDB 后第一个该敲的命令——它列出每个线程的 ID、状态(比如 Running 或 Stopped)、函数调用位置,以及是否是当前活跃线程(带 * 标记)。
常见错误现象:只执行 bt,结果只看到主线程栈,漏掉真正出问题的 worker 线程。原因就是没先确认哪条线程触发了 crash。
-
info threads输出中,注意看线程 ID(如2 Thread 0x7ffff73fe700)和对应函数名(如at my_worker_loop.cpp:42) - 如果线程状态显示
??或地址无法解析,说明符号缺失或solib-search-path没设对 - 多线程程序中,崩溃线程不一定是主线程;
info threads的输出顺序不反映执行顺序,只按内部 ID 排列
thread apply all bt 查看全部线程调用栈
单看 info threads 只知道“谁在线”,但不知道“谁在干什么”。thread apply all bt 会依次切换到每个线程并执行 bt,一次性打出所有线程的完整调用栈。
使用场景:你怀疑是锁竞争或某个异步回调导致崩溃,但不确定具体哪个线程卡在了哪里。
- 输出可能很长,重点关注带有明显业务函数名(比如
handle_request、process_packet)或异常地址(如0x0000000000000000)的栈帧 - 若某线程栈顶是
__pthread_cond_wait或sem_wait,大概率是正常阻塞,不是 crash 根源 - 若某线程栈顶是
free、memcpy、operator new且下一层地址非法,优先排查该线程
切换线程后 inspect 局部变量和寄存器
找到可疑线程后,用 thread <n> 切换过去(n 是 info threads 里显示的线程编号),再查细节。
为什么这样做:崩溃往往发生在某次内存访问时寄存器值已错位,或局部变量指针被提前释放。只看栈无法还原上下文。
-
info registers:重点看rip(崩溃指令地址)、rdi/rsi(常见参数寄存器)、rsp(栈顶)。若rip == 0或指向不可读内存,基本是野指针跳转 -
info locals:查看当前栈帧所有局部变量值。注意char *类型是否为0x0或指向0x7f...0000这类明显无效地址 -
p/x $rdi:直接打印寄存器内容,比info registers更快定位传参是否异常
容易忽略的符号与路径问题
即使 core 文件存在,info threads 和 bt 也可能只显示地址、不显示函数名——这不是命令错了,而是 GDB 找不到调试符号或共享库。
典型表现:bt 输出全是 #0 0x00007ffff7b8a387 in ?? (),info threads 里函数列为空或显示 ??。
- 必须确保可执行文件编译时加了
-g,且未 strip;release 版二进制默认无调试信息 - 如果 core 是在另一台机器上生成的,要手动设置符号路径:
set solib-search-path /path/to/libs/,否则 GDB 加载不了libstdc++.so等依赖的符号 -
file /path/to/binary必须在core-file前执行,否则 GDB 不知道该用哪个符号表去解析 core
最常被跳过的一步:没验证 file 命令是否成功加载了符号。敲完 file 后看终端是否提示 Reading symbols from ... (debugging symbols found)——没这句,后面所有分析都靠猜。


















