“程序突然不动了,不崩溃也不输出日志,CPU 忽高忽低,现场还在跑……我该怎么办?”
这是很多开发者(特别是写 C/C++的)都经历过的场景:程序卡住了,但又没有崩溃。
这时候最忌讳的操作就是直接 kill -9 干掉进程重新启动。
因为这样并没有解决问题,下次出现时依然会一脸懵:“卡在哪了?”
其实,只要程序还在运行,我们就能查清楚它到底在干嘛、卡在哪个函数、哪个线程。
本文就分享一种快速、实用的排查技巧,帮你把卡住的现场查个水落石出。
🔬 用 gdb 分析程序当前状态
gdb 是 Linux 上非常强大的调试工具。
即使表面上进程看起来卡住了,但只要进程还活着,我们就能用gdb接入它,查看每个线程此刻在干嘛。
步骤如下:
- 查找你的程序 PID:
ps aux | grep 你的程序名
- 使用 gdb 分析程序:
sudo gdb -p <PID>
- 查看所有线程的调用栈:
thread apply all bt
这条命令可以打印出所有线程的当前调用栈。
通过栈信息,你就可以判断:
- 是否卡在了锁相关函数(如
pthread_mutex_lock) ➜ 可能是死锁; - 是否在
select、recv、read➜ 可能是IO 阻塞; - 是否有线程一直在忙活 ➜ 可能是逻辑跑飞或死循环。
🧪 举个例子
下面我们用一个简单的死锁例子来实践下。
Demo代码:
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
std::mutex mtx;
void thread1_func() {
std::cout << "[Thread 1] Locking mutex and holding it forever...\n";
mtx.lock();
std::this_thread::sleep_for(std::chrono::hours(1)); // 模拟长期占有锁
mtx.unlock();
}
void thread2_func() {
std::this_thread::sleep_for(std::chrono::seconds(1)); // 保证 thread1 先拿到锁
std::cout << "[Thread 2] Trying to lock mutex...\n";
mtx.lock(); // 会卡住在这里
std::cout << "[Thread 2] Acquired lock!\n";
mtx.unlock();
}
int main() {
std::thread t1(thread1_func);
std::thread t2(thread2_func);
t1.join();
t2.join();
return 0;
}
编译执行后,你会发现程序打印如下两条log后就不动了:
[Thread 1] Locking mutex and holding it forever...
[Thread 2] Trying to lock mutex...
然后,我们使用本文的方法去分析它,可以看到gdb给了我们如下信息:

显然,它告诉我们,thread1_func()正在休眠,而thread2_func()正卡在获取锁的地方!
✅ 小结一下
下次遇到程序卡住时,可不要再马上 kill 掉进程重启了,那是宝贵的现场,试着用本文的方法分析一下吧😉
希望本文对你有帮助~
本文首发于微信公众号《Linux在秋名山》,欢迎大家关注~

1万+

被折叠的 条评论
为什么被折叠?



