用gdb附加进程后需手动发送SIGSTOP或按Ctrl+C中断死循环,再用info threads和bt定位卡在循环体内的线程;日志需加std::flush确保及时输出。

用 gdb 附加进程后直接看所有线程的调用栈
死循环通常不触发信号,gdb 无法自动中断,必须手动发送 SIGSTOP 或用 attach 后按 Ctrl+C 强制中断。此时所有线程都会停在当前执行点,真正跑飞的线程大概率卡在循环体内部。
- 启动
gdb:gdb -p <pid>,然后按Ctrl+C - 列出所有线程状态:输入
info threads,重点关注状态为running或刚被中断时 PC 偏移明显重复(比如总停在mov、jmp、test等跳转/比较指令)的线程 - 切换到可疑线程:用
thread <n>(n是线程 ID),再执行bt查看栈帧——如果顶层是你的函数且反复出现同一行(比如while (flag) { ... }中某条语句),基本就是它
std::this_thread::get_id() 配合日志打点要加 std::flush
靠日志定位的前提是日志能及时输出,否则死循环里缓冲区没刷出,你根本看不到最后一条 log。尤其在多线程下,std::cout 默认行缓冲,但循环内无换行就卡住。
- 写日志时别只写
std::cout - 必须显式刷新:后面加
<< std::flush,或改用std::cerr(默认未缓冲) - 更稳妥的做法:在循环入口、关键判断前后都打带线程 ID 的日志,并强制 flush;如果某条日志一直不出现,说明卡在它之前
Linux 下用 perf top -p <pid> 看热点指令
死循环本质是某个线程把 CPU 跑满,perf 能绕过源码直接看硬件级热点,比调试器更快暴露问题位置。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 运行
perf top -p <pid>,观察 “Overhead” 最高的符号——如果是你的函数名,再结合 “Symbol” 列看具体指令(如add、cmp、jmp) - 如果显示的是
__nanosleep或futex_wait,说明不是死循环,是锁争用或条件变量没唤醒,别误判 - 注意:需编译时加
-g,且perf对 inlined 函数可能只显示内联后的调用点,得结合perf report看详细栈
避免用 sleep(1) 这类低效轮询做“心跳”
很多死循环其实是人为写的“等待逻辑”,比如 while (!ready) sleep(1); —— 这看似安全,但一旦 ready 永远不置 true,就成了事实上的死循环,且 sleep 让 gdb 很难抓到现场。
立即学习“C++免费学习笔记(深入)”;
- 优先用
std::condition_variable::wait_for替代裸sleep,它可被通知打断,也方便调试器中断在 wait 点 - 若必须轮询,至少加超时退出机制:
for (int i = 0; i < 1000 && !ready; ++i) { std::this_thread::sleep_for(1ms); } - 别依赖全局变量 + 无锁读取做同步标志,
ready变量必须是std::atomic<bool>,否则编译器可能优化掉读取,导致无限循环
std::mutex::lock() 失败后没处理异常直接重试。先确认是不是真死循环,再动手查。

















