程序卡住了?先不要Kill!GDB来救你!

“程序突然不动了,不崩溃也不输出日志,CPU 忽高忽低,现场还在跑……我该怎么办?”

这是很多开发者(特别是写 C/C++的)都经历过的场景:程序卡住了,但又没有崩溃

这时候最忌讳的操作就是直接 kill -9 干掉进程重新启动。

因为这样并没有解决问题,下次出现时依然会一脸懵:“卡在哪了?”

其实,只要程序还在运行,我们就能查清楚它到底在干嘛、卡在哪个函数、哪个线程

本文就分享一种快速、实用的排查技巧,帮你把卡住的现场查个水落石出。

🔬 用 gdb 分析程序当前状态

gdb 是 Linux 上非常强大的调试工具。

即使表面上进程看起来卡住了,但只要进程还活着,我们就能用gdb接入它,查看每个线程此刻在干嘛。

步骤如下:

  1. 查找你的程序 PID:
ps aux | grep 你的程序名
  1. 使用 gdb 分析程序:
sudo gdb -p <PID>
  1. 查看所有线程的调用栈:
thread apply all bt

这条命令可以打印出所有线程的当前调用栈。

通过栈信息,你就可以判断:

  • 是否卡在了锁相关函数(如 pthread_mutex_lock) ➜ 可能是死锁
  • 是否在 selectrecvread ➜ 可能是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在秋名山》,欢迎大家关注~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux在秋名山

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值