gdb attach 后默认只显示当前线程,需执行 info threads 查看全部线程;切换线程用 thread 命令,bt 显示“no stack”说明线程未进入用户代码;断点全局有效但受 scheduler-locking 影响,应设为 off;attach 会发送 sigstop 冻结进程,需手动 continue。

直接 attach 就能进,但默认只停当前线程,其他线程照常跑 —— 这是绝大多数人卡住的第一步。
gdb attach pid 后线程全“消失”或只看到主线程
不是线程没了,是 info threads 没执行,或者执行了但没注意输出里带 * 号的当前线程。GDB attach 后默认只显示当前调度到的线程(通常是主线程),其余线程处于 sleeping / running 状态但不主动列出来。
- 必须手动运行
info threads才能看到全部线程列表,每行开头有 LWP ID(Linux Thread ID)和状态(e.g.running、sleeping、stopped) - 如果
info threads输出为空或只有 1 行,说明进程可能刚启动还没创建线程,或线程已全部退出 —— 不是 GDB 漏了,是程序本身没活跃线程 - 某些发行版(如 CentOS 7)的 GDB 版本较老,
info threads可能不显示完整状态,可配合ps -T -p <pid></pid>对比验证真实线程数
切换线程后 bt 显示“no stack”或地址乱码
常见于线程刚创建、正在执行 libc 初始化(如 __clone)、或已进入系统调用等待态。此时栈帧未建立完整,GDB 无法解析符号。
- 先用
thread <tid></tid>切过去(是 info threads里左边的数字,不是 OS PID) - 再运行
bt;若报No stack.,说明该线程尚未进入用户代码,可等几秒后重试 - 若
bt显示一堆?? (),检查是否编译时漏加-g,或程序用了 strip 剥离符号 ——file ./your_binary看输出里有没有 “not stripped” - 避免在
pthread_create返回前打断点,此时新线程栈还没 ready,GDB 容易失联
断点只在当前线程生效,切线程后断点失效
GDB 默认断点是全局的,但多线程下触发行为受 scheduler-locking 控制 —— 关键不是断点“失效”,而是其他线程根本没机会跑到断点位置。
- 用
set scheduler-locking off(默认是on),否则只有当前线程单步/continue,其他线程被锁死 - 用
break pthread_mutex_lock这类函数级断点时,所有线程都可能命中,但需注意:不同线程在不同时间点 hit,GDB 会暂停当前 hit 的线程,其他线程继续跑 - 想让所有线程在某个条件统一停住?靠
watch全局变量 +set scheduler-locking step配合,但慎用——容易死锁或错过时机
attach 后程序卡死或响应异常
不是 GDB 把程序搞挂了,而是 attach 动作本身会向目标进程发送 SIGSTOP,所有线程瞬间冻结;你没输 continue,它就一直停着。
- attach 完立即执行
continue或c,否则进程永远不动 - 如果
c后程序立刻退出,大概率是它原本就在崩溃边缘(比如已触发 SIGSEGV 但信号未 delivery),attach 只是让它暴露出来 - 生产环境慎用
attach调试高负载服务:短暂 freeze 可能导致超时、连接中断、状态错乱,优先考虑 core dump +gdb binary core
真正麻烦的从来不是怎么 attach,而是 attach 之后发现所有线程都在等同一个 mutex,而持有者早已 crash 却没释放 —— 这时候你得看 info proc mappings 和 thread apply all bt 全局堆栈,再结合日志交叉定位。别指望单靠一个 bt 就能定论。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











