百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

原创经验分享:低级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的主要代码

  1. int ti_ck_mutil(struct ck_self *ptiem, int len)

  2. {

  3. FILE *stream;

  4. char strout[256];

  5. int ret;

  6. int failcount = 0;

  7. for (int i = 0; i < len; i++) {

  8. printf("%s()%d\n", __FUNCTION__, __LINE__); //226行

  9. stream = popen(ptiem[i].dir, "r"); //未检查文件是否成功

  10. ret = fread( strout, sizeof(char), sizeof(strout), stream);

  11. strout[ret] = '\0';

  12. pclose(stream);

  13. // ...

  14. }

  15. return failcount;

  16. }

复制代码

fread输入参数只有4个,可能存在的错误无非是3点:

  • 被编译器优化后strout的缓存不是256(纯属胡乱猜测,可以通过查看map文件看到具体大小)

  • fread写入最后一个字符时溢出(实际我读写的文件不超过64byte,不应该超过256)

  • stream文件描述符无效

于是首先对fread修改,保证最后一个字符不被fread填写。

ret = fread( strout, sizeof(char), sizeof(strout) - 1, stream);

测试依旧崩溃

接着对stream检查,代码如下

  1. int ti_ck_mutil(struct ck_self *ptiem, int len)

  2. {

  3. FILE *stream;

  4. char strout[256];

  5. int ret;

  6. int failcount = 0;

  7. for (int i = 0; i < len; i++) {

  8. printf("%s()%d\n", __FUNCTION__, __LINE__); //226行

  9. stream = popen(ptiem[i].dir, "r"); //未检查文件是否成功

  10. if (NULL == stream) {

  11. continue;

  12. }

  13. // 读出内容,并在末尾添加字符串终结符号

  14. //存在溢出,应该用 sizeof(strout) - 1

  15. ret = fread( strout, sizeof(char), sizeof(strout) - 1, stream);

  16. strout[ret] = '\0';

  17. pclose(stream);

  18. // ...

  19. }

  20. return failcount;

  21. }

复制代码

测试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数据导入导出、歌曲上传下载、歌曲播放、用户注册登录注销等功能。难度等级:简单技术...

取消回复欢迎 发表评论: