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

gdb 调试技巧:定位程序卡死问题 程序卡住不退处,当然我这里的例子使用ctrl-c信号可以让程序退出,而我实际的程序是这里会卡死。不过这不是重点,重点是怎么知道程序卡死(或卡住)在哪里呢?当然这个简单的例子,你直接review代码就能看出,或者简单加几个printf就能定位出卡死的位置。遇到程序卡死不退处,可能不知道卡死在什么地方,如果程序非常简单,也许printf大法就可以很快定位。但是对于大型程序,尤其是一些框架程序,printf大法可能就力不从心了。最近遇到一个程序卡死的问题,借助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) ➜ 可能是死锁;
  • 是否在 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在秋名山》,欢迎大家关注~

中科蓝讯蓝牙耳机SDK实战:从目录解析到消息处理框架 本文深入解析中科蓝讯蓝牙耳机SDK的目录结构与消息处理框架,提供从硬件驱动到蓝牙功能定制的实战指南。重点剖析SDK核心模块如消息队列机制、按键事件处理及电量报告优化,并分享二次开发中的调试技巧与避坑经验,助力开发者高效完成TWS耳机功能定制。 阅读详情

相关推荐

告别130MB/s瓶颈!用Zynq+NVMe实现1.2GB/s高速存储的PL数据分流实战

本文详细介绍了如何通过Zynq+NVMe实现1.2GB/s高速存储的PL数据分流方案,突破传统Zynq架构130MB/s的瓶颈。文章分享了PL直连NVMe的硬件架构设计、软件栈优化及性能调优实战技巧,帮助开发者实现高速数据流的稳定存储。

weixin_42653691的博客 372

想看一个进程的 堆栈(stack)信息

命令作用bt最详细,调试视角快速查看所有线程堆栈查看主线程内核栈看是否卡在系统调用查看栈地址空间查看指定线程内核栈如果你能告诉我你是要分析什么样的程序(比如阻塞了?挂死了?死锁了?),我可以一步一步带你排查,还可以帮你写个一键堆栈收集脚本。要不要试试?

zjkyeah的博客 2403

Cursor+Playwright MCP实战:如何用自然语言一键生成UI自动化测试脚本

本文探讨了如何利用Cursor与Playwright MCP实现自然语言驱动的UI自动化测试脚本生成。通过智能IDE与浏览器自动化协议的结合,开发者可以高效创建稳定的测试脚本,显著提升测试效率与维护性。重点介绍了MCP架构的优势、项目结构最佳实践及团队协作规范,为自动化测试带来革命性改进。

k8l9m0n的博客 440

gdb调试死锁

gdb -p pid 列出所有线程 thread info 针对某个线程的堆栈进行分析 info thread_id bt

qq_39287722的博客 360

DeepSeek-OCR又更新:一起看下OCR1和OCR2

DeepSeek-AI 最近又又开源了,这次是DeepSeek-OCR2,结合之前发布的DeepSeek-OCR ,可以发现DeepSeek走出了一条不同于主流 OCR 方案的技术路线。第一代模型探索了**“视觉作为文本压缩介质”的可行性,打破了传统的序列长度限制;第二代模型则通过“Visual Causal Flow(视觉因果流)”**架构,将因果推理引入视觉编码器,解决了复杂排版下的阅读顺序难题。本文将从架构设计、逻辑结构、训练范式及工程实现四个维度,深度剖析这两代模型的异同与创新。

kakaZhui的博客 622

SAP 公司间库存调拨通过IDOC完成自动发票校验

本文仅用于SAP软件的应用与学习,不代表SAP公司。(注:文中所示截图来源SAP ERP软件,软件相应著作权归SAP所有。公司间采购时,通过SAP内部EDI 数据传输功能, 由销售方开的公司间发票自动触发采购方的发票校验。​欢迎扫码加如下微信,我会把大家拉到SAP PP学习群,随时欢迎跟我和其他SAP PP顾问一起交流和学习,如下图库存调拨订单,系统已经完成了发货方发货和收货方收货。

2402_84262664的博客 923

使用 GDB 调试多线程程序

info threads # 查看所有线程thread <id> # 切换线程bt # 当前线程栈回溯thread apply all bt # 所有线程的栈。

weixin_64612849的博客 578

ArcGIS 泛克里金插值

按照如图所示的步骤填写参数,1处选择subset features。 2:输入数据。 3:输出训练数据。 4:输出测试数据。 5:80,表示80%的比例是训练数据,20%是测试数据。 6:输入的百分比。 1:选择geostatistical wizard。 2:插值方法,克里金插值 3:训练数据。 4:数据字段。 点击下一步: 1:表示泛克里金插值。 2:输出表面类型。 3:转换类型none。 4:趋势剔除的阶数。 点击下一步: 表示东北—西南方向变化平缓。 1:模型优化 2:模型类型(stabl.

yuanYW7556的博客 7274

【Linux从入门到精通】进程的状态

当我们了解到进程是什么东西后,我们再来看看进程都会有那些状态。在Linux操作系统中,进程的状态包括运行状态(R)、等待(S)、被中断(D)、僵尸 (Z) 状态、停止(T)状态等。进程是现代操作系统中的一个重要概念,是指正在运行或等待操作系统分配资源的程序。在执行过程中,进程会出现不同的状态,这些状态描述了进程的不同状态,包括就绪、运行、阻塞和结束状态。

weixin_67596609的博客 2689

600份国家自然基金申报书--模板

600份国家自然基金申报书--模板

需要远程指导仿真实验、代码有问题的,请后台私信或者关注公众号 4186

RT-DETR目标检测模型性能评价指标详解,涉及混淆矩阵、F1-Score、IoU、mAP、参数量、计算量等,一文打尽所有评价指标

本文主要讲解的是计算机视觉网络模型的性能评价指标,这是每一篇论文中都需要展示的内容。熟悉每一个评价指标也能够帮助我们在训练和改进模型过程中,更好的观察模型的变化效果。

Limiiiing的博客 3357

不要使用kill -9 杀死进程,可以先使用kill -15

http://yqbjtu.blog.163.com/blog/static/529426201411042224375/ Perl语言专家Randal Schwartz在一篇短文里这样写: no no no.不要使用kill -9. 它没有给进程留下善后的机会: 1) 关闭socket链接 2) 清理临时文件 3) 将自己将要被销毁的消息通知给

vc66vcc的博客 3566

鲁棒优化 (Robust Optimization) 算法详解及案例分析

鲁棒优化是一种用于处理不确定性优化问题的方法。其目标是在不确定性参数的可能取值范围内,找到一个对不确定性具有鲁棒性的解。

闲人编程的博客 4327

no,no,不要使用kill -9

no,no,不要使用kill -9 no no no.不要使用kill -9. 它没有给进程留下善后的机会: 1) 关闭socket链接 2) 清理临时文件 3) 将自己将要被销毁的消息通知给子进程 4) 重置自己的终止状态 等等。 通常,应该发送15...

banexi8302的博客 130

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Linux kill、kill-15、kill-9区别

进程状态转换图 kill和kill -9,两个命令在linux中都有杀死进程的效果,然而两命令的执行过程却大有不同,在程序中如果用错了,可能会造成莫名其妙的现象。 执行kill(不加 -* 默认kill -15)命令,系统会发送一个SIGTERM信号给对应的程序。当程序接收到该signal信号后,将会发生以下事情: 程序立刻停止 当程序释放相应资源后再停止 程序可能仍然继续...

635

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

no no no. 不要使用kill -9

Perl语言专家Randal Schwartz在一篇短文里这样写: no no no.不要使用kill -9. 它没有给进程留下善后的机会: 1) 关闭socket链接 2) 清理临时文件 3) 将自己将要被销毁的消息通知给子进程 4) 重置自己的终止状态 等等。 通常,应该发送15,等一两秒钟,如果没效果,发送2,如果还不行,发送1。 如果还不行,那你应该把那个

北雨南萍 1054

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

mysql kill hup_Linux kill、kill-15、kill-9区别

进程状态转换图kill和kill -9,两个命令在linux中都有杀死进程的效果,然而两命令的执行过程却大有不同,在程序中如果用错了,可能会造成莫名其妙的现象。执行kill(不加 -* 默认kill -15)命令,系统会发送一个SIGTERM信号给对应的程序。当程序接收到该signal信号后,将会发生以下事情:程序立刻停止当程序释放相应资源后再停止程序可能仍然继续运行大部分程序接收到SIGTER...

weixin_39767983的博客 518

kill 和 kill -9 的区别

原文地址: https://www.cnblogs.com/aspirant/p/11543456.html https://www.cnblogs.com/aspirant/ 进程状态转换图 kill和kill -9,两个命令在linux中都有杀死进程的效果,然而两命令的执行过程却大有不同,在程序中如果用错了,可能会造成莫名其妙的现象。 执行kill(不加 -* ...

weixin_42518604的博客 5044

在使用kill -9前,你应该先使用kill -15

Perl语言专家Randal Schwartz在一篇短文里这样写:    no no no.不要使用kill -9.    它没有给进程留下善后的机会:    1) 关闭socket链接    2) 清理临时文件    3) 将自己将要被销毁的消息通知给子进程    4) 重置自己的终止状态    等等。    通常,应该发送15,等一两秒钟,如

u013177084的专栏 1292

不要使用kill -9

kill -9 没有给进程留下善后的机会: 1)关闭socket链接; 2)清理临时文件; 3)将自己快要给销毁的消息通知给子进程; 4)重置自己的终止状态; 通常,应该发送15,等一两秒钟,如果没有效果,发送2,如果还不行,发送1. 总之,在使用kill -9前,你应该先使用kill -15,给目标进程一个清理善后工作的机会。(进程也许无法捕捉或直接忽略SIGKILL信号,但他们...

wang_2011_ying的专栏 607

慎用kill -9,kill -15的作用

Perl语言专家Randal Schwartz在一篇短文里这样写: no no no.不要使用kill -9. 它没有给进程留下善后的机会: 1) 关闭socket链接 2) 清理临时文件 3) 将自己将要被销毁的消息通知给子进程 4) 重置自己的终止状态 等等。 通常,应该发送15,等一两秒钟,如果没效果,发送2,如果还不行,发送1。如果还不行,那你应该把那个程序删掉,因为那个程序写的太烂了! 不要使用kill -9。不要用收割机来修...

weixin_41869893的博客 751

kill进程_你还在使用kill -9 杀进程吗?从原理谈避免踩雷!

你要“跑路”了吗?只要你用过 UNIX/LINUX ,我敢打赌你大概率执行过这样一条命令,也就是俗话说的“杀进程”:kill -9执行它,是不是如同执行以下命令一样酸爽:rm -rf因为他带来了一种感觉和预期,那就是:别拦我,我要跑路了!同样是杀进程, kill -9 有什么特别之处 ?Perl 大牛 Randal Schwartz 这样描述过:no no no,不要使用kill -9。它没有给进...

weixin_39633452的博客 1130

linux gdb 调试多线程

1 用 kill 命令产生 core dump文件:   kill -11 pid 用信号11杀掉它,会让进程产生一个 Segmentation Fault,从而产生一个 core dump,得到一个 core 文件,里面包含了死锁的时候,进程的内存镜像。 2 gdb 打开这个 core 文件,然后   thread apply all bt 意思是让所有的线程执行bt 命令是:thr...

icebergliu1234的博客 1045

尽量避免直接使用 kill -9

kill -9 没有给进程留下善后的机会: 1)关闭socket链接; 2)清理临时文件; 3)将自己快要给销毁的消息通知给子进程; 4)重置自己的终止状态。

zhouxukun123的专栏 2066
上一篇: 使用C++做一个进度条
下一篇: C++ std::optional,让代码更优雅
Linux在秋名山
博客等级 码龄9年 225粉丝 53原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

Linux在秋名山

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

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

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

打赏作者

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

抵扣说明:

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

余额充值