原创经验分享:低级bug耗费12小时Fix
nanshan 2025-07-10 19:31 5 浏览 0 评论
调试某程序非常简单的程序,简单到认为不可能存在缺陷,但该BUG处理时间超过12小时:
程序属于后台进程,监控系统每隔15秒检查外设IO状态,IO异常后发出报警或复位外设,外设都在linux下有/sys/class等文件节点。
程序有规律性4-5小时后崩溃
程序崩溃原因也非常简单:
某文件反复打开未释放,打开文件数超过linux单进程最大打开文件数。
未对文件打开成功检查,持无效文件描述符写文件导致Segmentation fault
下面是排除过程
下面是程序运行打印信息,可看到文件在调用ti_ck_mutil函数第266行时崩溃
TickStatusIO():124
ti_ck_mutil():266
ti_ck_mutil():272
ti_ck_mutil():276
TickStatusIO():105
ti_ck_mutil():266
Segmentation fault (core dumped)
gdb打开coredump查看栈状态
(gdb) bt
#0 0x401b28e0 in vfwprintf () from /lib/libc.so.6
#1 0xe92d47f0 in ?? ()
#2 0x00009d10 in ti_ck_mutil (ptiem=0xbebffa4c, len=1) at src/ckself.c:268
#3 0x00008e2c in TickStatusIO () at src/initgpio.c:106
#4 0x00009238 in main (argc=1, argv=0xbebffbf4) at src/initgpio.c:304
最终显示在c库函数vfwprintf里崩溃,并在在二行的栈地址以及崩溃了,显示" in ?? ()",他的调用者正是ti_ck_mutil,并且更进一步显示崩溃点在268行而不是266行。
如下是ti_ck_mutil的主要代码
int ti_ck_mutil(struct ck_self *ptiem, int len)
{
FILE *stream;
char strout[256];
int ret;
int failcount = 0;
for (int i = 0; i < len; i++) {
printf("%s()%d\n", __FUNCTION__, __LINE__); //226行
stream = popen(ptiem[i].dir, "r"); //未检查文件是否成功
ret = fread( strout, sizeof(char), sizeof(strout), stream);
strout[ret] = '\0';
pclose(stream);
// ...
}
return failcount;
}
复制代码
fread输入参数只有4个,可能存在的错误无非是3点:
被编译器优化后strout的缓存不是256(纯属胡乱猜测,可以通过查看map文件看到具体大小)
fread写入最后一个字符时溢出(实际我读写的文件不超过64byte,不应该超过256)
stream文件描述符无效
于是首先对fread修改,保证最后一个字符不被fread填写。
ret = fread( strout, sizeof(char), sizeof(strout) - 1, stream);
测试依旧崩溃
接着对stream检查,代码如下
int ti_ck_mutil(struct ck_self *ptiem, int len)
{
FILE *stream;
char strout[256];
int ret;
int failcount = 0;
for (int i = 0; i < len; i++) {
printf("%s()%d\n", __FUNCTION__, __LINE__); //226行
stream = popen(ptiem[i].dir, "r"); //未检查文件是否成功
if (NULL == stream) {
continue;
}
// 读出内容,并在末尾添加字符串终结符号
//存在溢出,应该用 sizeof(strout) - 1
ret = fread( strout, sizeof(char), sizeof(strout) - 1, stream);
strout[ret] = '\0';
pclose(stream);
// ...
}
return failcount;
}
复制代码
测试4小时后程序不崩溃,但当IO异常后也既不报警也不复位,相当于程序不工作了,由上面代码可知必定是popen失败导致,函数内部一直continue。
查看man popen
RETURN VALUE
The popen() function returns NULL if the fork(2) or pipe(2) calls fail, or if it cannot allocate memory.
man fork
RETURN VALUE
On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is
returned in the parent, no child process is created, and errno is set appropriately.
问题很明显popen的失败是由于fork函数失败或内存不足,而这两个失败的原因是不能创建子进程。
该程序运行内存极小,不可能引发内存不足。
根据经验linux对每个用户默认打开文件数做了限制,也预示着代码里有未释放的文件描述符
为了证明再次运行应用程序,接着每秒查看程序打开的文件个数
watch -n 1 ls /proc/<pid>/fd
果不其然文件个数每15s递增一个。当达到最大限制1024后文件打开失败,ti_ck_mutil只能continue,也就是原始程序在大约4小时崩溃的原因(15s打开新文件,大约4.2小时达到1024上限)
全工程搜索open关键词,看各调用后是否存在close,果然有个opendir后忘记closedir。
加上后bug解决。
以上图文内容均是EEWORLD论坛网友:lzwml原创,在此感谢。
欢迎微博@EEWORLD
如果你也写过此类原创干货请关注微信公众号:EEWORLD(电子工程世界)回复“投稿”,也可将你的原创发至:bbs_service@eeworld.com.cn,一经入选,我们将帮你登上头条!
与更多行业内网友进行交流请登陆EEWORLD论坛。
相关推荐
- 雷军1994年写的老代码曝光,被称像诗一样优雅
-
大数据文摘授权转载自程序员的那些事雷军的代码像诗一样优雅↓↓↓有些网友在评论中质疑,说雷军代码不会是“屎”一样优雅吧。说这话的网友,也许是开玩笑的,也许是真没看过雷军写过的代码。在2011年的时候,我...
- 原创经验分享:低级bug耗费12小时Fix
-
调试某程序非常简单的程序,简单到认为不可能存在缺陷,但该BUG处理时间超过12小时:程序属于后台进程,监控系统每隔15秒检查外设IO状态,IO异常后发出报警或复位外设,外设都在linux下有/sys/...
- SpringBoot实现的简单停车位管理系统附带导入和演示教程视频
-
这一次为大家带来的是简单的停车位管理系统,基于SpringBoot+Thymeleaf+Mybatis框架,这个系统相对来说比较简单,很容易学习并快速上手,因为逻辑很清晰,没有太复杂的代码逻辑,所以学...
- 一个开箱即用的代码生成器(代码自动生成工具开源)
-
今天给大家推荐一个好用的代码生成器,名为renren-generator,该项目附带前端页面,可以很方便的选择我们所需要生成代码的表。首先我们通过git工具克隆下来代码(地址见文末),导入idea。...
- 【免费开源】JeecgBoot单点登录源码全部开源了
-
JeecgBoot单点登录源码全部开源了,有需要的朋友可以来薅羊毛了。一、JeecgBoot介绍JeecgBoot是一款企业级的低代码平台!前后端分离架构SpringBoot2.x,SpringCl...
- SpringBoot+JWT+Shiro+Mybatis实现Restful快速开发后端脚手架
-
作者:lywJee来源:cnblogs.com/lywJ/p/11252064.html一、背景前后端分离已经成为互联网项目开发标准,它会为以后的大型分布式架构打下基础。SpringBoot使编码配置...
- 为什么越来越多的人选择使用idea软件
-
IDEA软件是什么?IDEA软件是干什么的?为什么越来越多的人选择使用IDEA软件?IDEA软件,全称IntelliJIDEA,它是由JetBrains公司开发开发的一款功能强大的集成开发环境(ID...
- 开题报告大学生互助系统(附源码)java毕设
-
本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容选题背景随着互联网技术的飞速发展,大学生群体对信息共享与互助的需求日益增长。关于大...
- SpringBoot项目快速开发框架JeecgBoot——项目简介及系统架构!
-
项目简介及系统架构JeecgBoot是一款基于SpringBoot的开发平台,它采用前后端分离架构,集成的框架有SpringBoot2.x、SpringCloud、AntDesignof...
- 新手配电脑13代CPU怎么选择(新手配电脑13代cpu怎么选择好)
-
Intel第13代酷睿i3、i5、i7、i9系列处理器的核心参数、性能差异及适用群体的详细说明(以桌面端为例):一、13代酷睿全系参数对比(桌面端主流型号)参数i3-13100i5-13600Ki7-...
- 加速 SpringBoot 应用开发,官方热部署神器真带劲
-
平时使用SpringBoot开发应用时,修改代码后需要重新启动才能生效。如果你的应用足够大的话,启动可能需要好几分钟。有没有什么办法可以加速启动过程,让我们开发应用代码更高效呢?今天给大家推荐一款Sp...
- 基于微信小程序的移动端物流系统-计算机毕业设计源码+LW文档
-
摘要随着Internet的发展,人们的日常生活已经离不开网络。未来人们的生活与工作将变得越来越数字化,网络化和电子化。网上管理,它将是直接管理移动端物流系统app的最新形式。本论文是以构建移动端物流系...
- springboot教务管理系统+微信小程序云开发附带源码
-
今天给大家分享的程序是基于springboot的管理,前端是小程序,系统非常的nice,不管是学习还是毕设都非常的靠谱。本系统主要分为pc端后台管理和微信小程序端,pc端有三个角色:管理员、学生、教师...
- SpringBoot全家桶:23篇博客加23个可运行项目让你对它了如指掌
-
SpringBoot现在已经成为Java开发领域的一颗璀璨明珠,它本身是包容万象的,可以跟各种技术集成。本项目对目前Web开发中常用的各个技术,通过和SpringBoot的集成,并且对各种技术通...
- Maven+JSP+Servlet+C3P0+Mysql实现的音乐库管理系统
-
本系统基于Maven+JSP+Servlet+C3P0+Mysql实现的音乐库管理系统。简单实现了充值、购买歌曲、poi数据导入导出、歌曲上传下载、歌曲播放、用户注册登录注销等功能。难度等级:简单技术...
你 发表评论:
欢迎- 一周热门
-
-
UOS服务器操作系统防火墙设置(uos20关闭防火墙)
-
极空间如何无损移机,新Z4 Pro又有哪些升级?极空间Z4 Pro深度体验
-
如何修复用户配置文件服务在 WINDOWS 上登录失败的问题
-
手机如何设置与显示准确时间的详细指南
-
如何在安装前及安装后修改黑群晖的Mac地址和Sn系列号
-
日本海上自卫队的军衔制度(日本海上自卫队的军衔制度是什么)
-
NAS:DS video/DS file/DS photo等群晖移动端APP远程访问的教程
-
爱折腾的特斯拉车主必看!手把手教你TESLAMATE的备份和恢复
-
10个免费文件中转服务站,分享文件简单方便,你知道几个?
-
FANUC 0i-TF数据备份方法(fanuc系统备份教程)
-
- 最近发表
- 标签列表
-
- linux 查询端口号 (58)
- docker映射容器目录到宿主机 (66)
- 杀端口 (60)
- yum更换阿里源 (62)
- internet explorer 增强的安全配置已启用 (65)
- linux自动挂载 (56)
- 禁用selinux (55)
- sysv-rc-conf (69)
- ubuntu防火墙状态查看 (64)
- windows server 2022激活密钥 (56)
- 无法与服务器建立安全连接是什么意思 (74)
- 443/80端口被占用怎么解决 (56)
- ping无法访问目标主机怎么解决 (58)
- fdatasync (59)
- 405 not allowed (56)
- 免备案虚拟主机zxhost (55)
- linux根据pid查看进程 (60)
- dhcp工具 (62)
- mysql 1045 (57)
- 宝塔远程工具 (56)
- ssh服务器拒绝了密码 请再试一次 (56)
- ubuntu卸载docker (56)
- linux查看nginx状态 (63)
- tomcat 乱码 (76)
- 2008r2激活序列号 (65)