能,通过gcore命令可主动为挂死进程生成core dump快照;需确保进程未被ptrace限制、权限足够且状态为r/s/t,再用gdb分析各线程调用栈与锁状态定位停滞点。

core dump 能不能抓到挂死(hang)?
不能直接抓——core dump 是进程**异常终止**时由内核生成的内存快照,而挂死(比如死锁、无限等待、信号阻塞)通常不触发任何信号,进程仍处于 R 或 S 状态,不会自动生成 core 文件。
但你可以主动“制造”一个:用 gcore 命令对正在运行的疑似挂死进程强制生成快照。前提是进程没被 ptrace 限制(如被其他调试器 attach),且你有权限读取其内存。
-
gcore -o /tmp/core.hang <pid></pid>—— 最常用,生成带时间戳的 core 文件 - 若
gcore失败(如权限不足或进程拒绝 dump),可尝试kill -SIGABRT <pid></pid>,部分程序会捕获该信号并调用abort(),从而触发真正的core dump - 注意:不要用
SIGKILL(kill -9),它不会留任何现场
gdb 里怎么看哪个线程卡住了?
挂死问题本质是线程停滞,关键不是看崩溃点,而是看所有线程的当前状态和调用栈是否“静止”或“循环等待”。
- 启动:
gdb ./your_program /tmp/core.hang - 列出所有线程:
info threads—— 观察 LWP ID 和状态(running、sleeping、idle都可疑;stopped是正常暂停) - 切换到可疑线程:
thread <n></n>(N 是info threads中显示的 GDB 线程号,不是 OS PID) - 看栈帧:
bt—— 如果停在pthread_mutex_lock、sem_wait、__lll_lock_wait或nanosleep上,基本就是等锁/等信号/等条件变量 - 检查锁状态:
info proc mappings看内存布局,info registers看指令指针是否卡在一条重复指令上(比如 spin lock 的 tight loop)
怎么确认是不是死锁?
死锁需要至少两个线程互相持有对方需要的资源,gdb 本身不自动检测,但能帮你验证四个必要条件是否满足。
- 先用
info threads找出所有阻塞在线程同步原语上的线程(比如都卡在pthread_mutex_lock) - 对每个线程执行
bt,看它持有了哪些锁(通过源码或print查看局部互斥量对象地址) - 再看它正试图获取哪个锁 —— 如果线程 A 持有
mtx1并等待mtx2,而线程 B 持有mtx2并等待mtx1,就是典型死锁 -
info mutex在较新 GDB(≥8.0)中可用,能列出当前进程中所有已初始化的pthread_mutex_t及其 owner,但仅限于未被优化掉的变量;若用了std::mutex且编译时没加-O0,可能看不到
为什么有时候 bt 显示 “corrupt stack” 或 “no stack”?
挂死不等于崩溃,但长期挂住的线程可能因栈耗尽、内存踩坏或信号处理异常导致栈帧不可靠。这时候不能只信 bt,得交叉验证。
- 如果
bt报错或输出极短,试试disassemble $pc看当前指令,结合x/10i $pc查看附近汇编 - 用
thread apply all bt强制打印所有线程栈,哪怕部分损坏,也能看出哪些线程行为一致(比如全卡在同一个函数入口) - 检查线程栈大小:
cat /proc/<pid>/maps | grep stack</pid>(需原始进程还在);若怀疑栈溢出,看栈顶附近内存是否可写(vmmap或info proc mappings) - 最实用的一招:
thread apply all p (char*)$rsp—— 打印各线程栈指针附近的内存内容,常能发现被覆盖的栈帧或残留的函数名字符串
挂死分析真正难的不是工具操作,而是从一堆看似正常的栈帧里识别出“不该停在这里”的逻辑停滞点——比如一个本该超时退出的 wait_for 却永远没返回,或者一个条件变量 wait 的 predicate 始终为 false 却没人 notify。这需要你对业务同步逻辑足够熟悉,否则 core dump 只是一张静态快照,拍不出动态意图。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











