Linux 多线程调试(内存占用、死循环、CPU占用率高……)

2023-11-16

你的软件在某个时刻停止服务,CPU占用达到100%+,这种问题一个可能的原因是产生了死循环,假设程序某处存在潜在的死循环,并在某种条件下会引发,本文以一个示例来定位出现死循环的位置。
当程序某处存在死循环,通常定位问题及缩小范围的方法是,在可疑的代码处加log,或者注释掉可疑代码,这对于容易重现问题的程序来说还好,但对于“偶尔”才会产生问题程序却很难调试,因为我们很难重现程序故障。本文所述的调试过程正是在这种情况下,假设问题已经出现,我们要求环境保护现场,即出问题的程序还在运行中。

1.我们首先要知道是哪个线程出了问题:
首先查一下出问题进程的pid,例如

ovtsvn@ovtsvn: ~/MASS4/src/icdn/src$ ps  - ef  |  grep icdn 
ovtsvn    11065       1   50   11 : 57   ?          00 : 00 : 07  . / icdn 
ovtsvn    11076   10971    0   11 : 57  pts / 2      00 : 00 : 00  grep
ovtsvn@ovtsvn: ~/ MASS4 / src / icdn / src$
ovtsvn@ovtsvn: ~/ MASS4 / src / icdn / src$ 

然后top命令查看线程信息:
top -H -p 11065

PID USER      PR  NI  VIRT  RES  SHR S  % CPU  % MEM    TIME +   COMMAND                                                                 
11073  ovtsvn     25     0   325m  3980   2236  R   100    0.4     1 : 40.84  icdn                                                                    
11065  ovtsvn     18     0   325m  3980   2236  S     0    0.4     0 : 00.01  icdn                                                                    
11066  ovtsvn     18     0   325m  3980   2236  S     0    0.4     0 : 00.00  icdn                                                                    
11067  ovtsvn     15     0   325m  3980   2236  S     0    0.4     0 : 00.00  icdn                                                                    
11068  ovtsvn     15     0   325m  3980   2236  S     0    0.4     0 : 00.00  icdn                                                                    
11069 ovtsvn  18 0  325m  3980 2236  S  0 0.4 0 : 00.00  icdn 
11070  ovtsvn  18 0  325m  3980 2236  S  0 0.4 0 : 00.00  icdn 
11071  ovtsvn  22 0  325m  3980 2236  S  0 0.4 0 : 00.00  icdn 
11072  ovtsvn  15 0  325m  3980 2236  R  0 0.4 0 : 00.00  icdn
 

从上面可以看出,出问题线程PID为11073

2.接下来,我们用gdb来attach目标进程
执行: gdb icdn 11065
在gdb中,列出线程状态:

(gdb) info threads   
9  Thread  47056948181264  (LWP  11066 )   0x00002acc4a3dec91   in  nanosleep () from  / lib / libc.so. 6    
8  Thread  47056956573968  (LWP  11067 )   0x00002acc4a406fc2   in  select () from  / lib / libc.so. 6    
7  Thread  47056964966672  (LWP  11068 )   0x00002acc4a3dec91   in  nanosleep () from  / lib / libc.so. 6   
  6  Thread  47056973359376  (LWP  11069 )   0x00002acc4a3dec91   in  nanosleep () from  / lib / libc.so. 6    
5  Thread  47056981752080  (LWP  11070 )   0x00002acc4a3dec91   in  nanosleep () from  / lib / libc.so. 6    
4  Thread  47056990144784  (LWP  11071 )   0x00002acc4a40e63c   in  recvfrom () from  / lib / libc.so. 6    
3  Thread  47057194060048  (LWP  11072 )   0x00002acc4a406fc2   in  select () from  / lib / libc.so. 6    
2  Thread  47057226893584  (LWP  11073 )  CSendFile::SendFile ( this = 0x2acc5d4aff40 , pathname = @ 0x2acc5d4afee0     at .. / src / csendfile.cpp: 101    
1  Thread  47056939784832  (LWP  11065 )   0x00002acc4a3dec91   in  nanosleep () from  / lib / libc.so. 6  (gdb) 


gdb已经列出了各线程正在执行的函数,我们需要更多信息,记住11073对应的行首标号,这是gdb为线程分配的id,这里为2,然后执行切换:

(gdb) thread  2  
[Switching to thread  2  (Thread  47057226893584  (LWP  11073 ))]# 0   CSendFile::SendFile ( this = 0x2acc5d4aff40 , pathname = @ 0x2acc5d4afee0     at .. / src / csendfile.cpp: 101   101               while ( 1
(gdb) 

bt一下:

(gdb) bt 
# 0   CSendFile::SendFile ( this = 0x2acc5d4aff40 , pathname = @ 0x2acc5d4afee0 ) at .. / src / csendfile.cpp: 101  
# 1    0x000000000040592e   in  CIcdn::TaskThread (pParam = 0x7fff617eafe0 ) at .. / src / cicdn.cpp: 128  
# 2    0x00002acc4a90b73a   in  start_thread () from  / lib / libpthread.so. 0  
# 3    0x00002acc4a40d6dd   in  clone () from  / lib / libc.so. 6  
# 4    0x0000000000000000   in   ??  ()


来看一下101行的代码:

(gdb) l 
96       } 
97  
98        int  CSendFile::SendFile( const   string &  pathname) 
99        {
100             int n;
101             while(1)
102             {
103                     n++;
104             }
105             //read file and send 

现在我们定位到了出问题的代码位置,这里的循环只用来演示的。 
最后别忘了detach()

调试完指定进程后,可以运行detach命令来让GDB释放该进程,该进程得以继续运行。当回车时,detach不会重复。当执行完detach后,进程和GDB不再相关,GDB可以attach其他进程。

 


from: http://www.cnblogs.com/cy568searchx/archive/2013/10/28/3391790.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux 多线程调试(内存占用、死循环、CPU占用率高……) 的相关文章

随机推荐

  • 如何成为一名合格的前端开发者?

    个人 懂得都懂 我觉得会 Ctrl C 和 Ctrl V 才是合格 这是对老板讲的 一 JavaScript基础 前端工程师吃饭的家伙 深度 广度一样都不能差 变量和类型 1 JavaScript规定了几种语言类型 2 JavaScript
  • k8s系统获取真实客户端ip

    k8s部署 系统获取真实客户端ip 我们生产中使用的是kong网关环境的架构也不同 第一种kong网管后走nginx 第二种kong网管后不走nginx kong网管后走ingress nginx 修改kong的配置 配置要信任的原始IP地
  • 使用python做手机app后台

    编辑器 HBuiderX PyCharm 主要技术 5 App python HBuiderX 下载地址 http www dcloud io hbuilderx html PyCharm 下载地址 http www jetbrains c
  • 如何在html里写css类选择器,关于html:如何在CSS选择器中排除特定的类名?

    当用户鼠标将鼠标悬停在类名称为 reMode hover 的元素上时 我尝试应用背景色 但是如果元素也有 reMode selected 我不想更改颜色 注意 因为我在某种有限的环境中工作 所以只能使用CSS而不是JavaScript 为了
  • ASN.1 常用类型 编码详解 入门

    文章目录 编码结构 标识符 Identifier 长度 Length 短形式 长形式 内容 Contents 基本类型 布尔类型 BOOLEAN 整形 INTEGER 实数 REAL 枚举类型 ENUMERATED 二进制的编码 十进制的编
  • 微信测试号 如何配置服务器配置,微信测试号配置失败

    appID wxd281df297a6dc834 appsecret 20b2deacfa8a9e88a9afcbbe12da1f31 define TOKEN weixin function checksignature signatur
  • openGL之API学习(三十三)查看opengl、显卡的信息

    const GLubyte name glGetString GL VENDOR 返回负责当前OpenGL实现厂商的名字 const GLubyte biaoshifu glGetString GL RENDERER 返回一个渲染器标识符
  • LWIP学习笔记(2)---ARP简析

    ARP协议概述 即地址解析协议 用于实现从 IP 地址到 MAC 地址的映射 即询问目标IP对应的MAC地址 ARP分组格式 以太网目的地址 MAC 以太网源地址 MAC 帧类型 硬件类型 协议类型 OP 发送端目的地址 发送端 地址 目的
  • Selenium 高频面试题及答案

    1 什么是 Selenium 它用于做什么 Selenium 是一个用于自动化测试的开源框架 它提供了多种工具和库 用于模拟用户在不同浏览器和操作系统上的行为 并且可用于测试网页应用程序 2 Selenium WebDriver 和 Sel
  • 2023前端面试题及答案整理(CSS)

    盒模型 标准盒模型 W3C标准 一个块的总宽度 内容宽度 margin 左右 padding 左右 border 左右 怪异盒模型 IE标准 一个块的总宽度 width 包含 padding 和 border margin 左右 怪异盒模型
  • C++并发编程框架Theron(8)——Theron中包含的类(二)

    1 前言 本篇文章主要接着上一篇来介绍Theron框架库中包含的类 上一篇中主要介绍了Theron下Actor Address AllocatorManager和Catcher类 在本篇文章中我会相继介绍DefaultAllocator E
  • 解决vscode找不到arduino esp8266头文件

    用Arduino IDE写ESP8266没有代码补全 不能跳转查看头文件 个人觉得这是最难受的 vscode装上Microsoft的arduino扩展后 有时候会找不到头文件 刚开始自己傻傻的一个个往includePath里面添加 后来在引
  • 决策树(Decision Tree)简介

    决策树 Decision Tree 及其变种是另一类将输入空间分成不同的区域 每个区域有独立参数的算法 决策树分类算法是一种基于实例的归纳学习方法 它能从给定的无序的训练样本中 提炼出树型的分类模型 树中的每个非叶子节点记录了使用哪个特征来
  • 李宏毅机器学习课程第4讲:Estimator

    李宏毅机器学习课程第4讲 Estimator 味儿太冲了 开头又是宝可梦哈哈哈哈哈 不过听了这一讲 我对于过拟合和欠拟合的理解更深刻了 李老师从Bias和Variance两个角度进行了解释 对 于 这 样 一 个
  • linux centos7 centos8 Rocky8.8 Rocky9.2 sed错误sed: -e expression #1, unknown option to `s‘解决办法

    报错如下 sed e expression 1 char 13 unknown option to s 需要替换的行为 monitor url http 192 168 25 100 8443 rest 查询资料得知 报错是因为替换的字符串
  • 高等数学(工本)填空题

    1 2 3 4 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 4
  • Error: listen EADDRINUSE: address already in use 127.16.20.217:8090

    端口占用npm run staert无效 今天遇到一个问题 就是在提交代码时怕把本地端口号提交到远程 然后将已经启用的端口设置为localhost 待提交完代码后再刷新页面 结果一直更新不出来 然后重启代码 终端报 Error listen
  • 怎么上传代码到GitHub

    怎么上传代码到GitHub 2021 9 我们想要把代码上传到github上面用git管理 但是怎么操作呢 首先在本地电脑安装git 和在github上面注册账号 git下载地址 git官网链接 然后我们要知道有二种方式可以配置操作 一种是
  • 机器学习有监督学习之--回归

    一 引言 本材料参考Andrew Ng大神的机器学习课程 http cs229 stanford edu 以及斯坦福无监督学习UFLDL tutorial http ufldl stanford edu wiki index php UFL
  • Linux 多线程调试(内存占用、死循环、CPU占用率高……)

    你的软件在某个时刻停止服务 CPU占用达到100 这种问题一个可能的原因是产生了死循环 假设程序某处存在潜在的死循环 并在某种条件下会引发 本文以一个示例来定位出现死循环的位置 当程序某处存在死循环 通常定位问题及缩小范围的方法是 在可疑的