记录关于智能家居的路程的一个bug___Segmentation fault(段错误)

前言

其实发生段错误的情况有很多:

其实在项目的开发中最有可能的错误就是①和②,考虑到本项目数组用的比较少,所以主要是考虑错误①指针的误用。

有时候错误就是那么离谱,声音也算是一种设备?????

出错原因:对语音模块发出开机的指令就会出现段错误,然后各种错误

有时候又没有段错误

找bug的过程:

第一次找:

怀疑是多线程的问题,把线程一个一个注释掉,发现第四个线程注释掉就不会出现“Segmentation fault”

解决思路:

对比其他三个线程的结构,有没有什么不一样。

对比下来发现,功能其实差的比较大,receive线程的主要目的是接收处理数据,而其他3个都是直接添加设备,果断转战下一个解决思路。 

ps:这里补充VsCode的一个对比工具“Partial Diff”插件

差异对比犀利手册:使用 Partial Diff 插件在 VSCode 中比较代码差异_vscode提交代码对比插件-CSDN博客

还补充了 gdb调试 的基本步骤

---------------------------------------------------------------------------------------------------------------------------------

第二次找:

在receive线程里面一句一句的排查注释,最终锁定一段代码、一句话

解决思路:

其实仔细一想,也不是这里的问题,这里只是初始化,情况内存,不是核心问题(因为此时的核心问题没有找,所以根本发现不了,只能挨着继续往下寻找)

---------------------------------------------------------------------------------------------------------------------------------

第三次找:

进一步排查,发现是该函数的memset的下面一句发生了错误,同样也发生了错误

解决思路:

排查到这句话,现在想起来其实是可以说明 cur_gdev->gpio_status 的状态是有问题的,只是当时不清楚,排查不到这里去。当时的解决思路完全是去纠结这里的语法去了

第一次改 :strcpy(change_status, cur_gdev->gpio_status == LOW ? "Open" : "Close");

修改的原因是:考虑字符串不能直接赋值。

但是不幸的是仍然是报错

所以又试了试不用三目运算符来写一下试试???

发现还是不行还是段错误。

继续考虑,会不会是指针没有分配到地址??

还是报错!

此时又回过头来考虑语法的问题

想了想 change_status 是一个指针,而 cur_gdev->gpio_status 是一个int类型,这两个能直接比较吗?

而且能够把字符串赋值给int类型的变量吗?现在想想都觉得当时写的很好笑

这个时候就应该考虑让 gpio_status 与一个数字作比较来判断高低电平

if (gpio_status == 0)

以及用 strcpy() 来对字符串赋值

但是仍然是报错!!!!

此时的报错原因 就是,语音模块的开机,“你好 小美” 就会出现段错误

没办法继续找吧,但是此时可以确定,该程序能不能跑到这里去

-------------------------------------------------------------------------------------------------------------------------------

第四次找:

还是把这段注释掉就不会崩,此时还是没有找到报错的核心问题

---------------------------------------------------------------------------------------------------------------------------------

第五次找:

第四次找的每一步都加上打印,最后确定查询到哪里停止

解决思路:

推荐方法 : printf("running %d \n",__LINE__); 

如果程序崩了的话就看看running停在了哪里 哪里就是问题所在 

现在可以基本上确定问题所在 “change_status”的数据没有,所以造成了错误,逐渐向真相靠近

并且把这一步注释掉,没有任何意义,根本copy不了,gpio_status 这玩意又不是指针,所以留着也没什么意义

这一句的作用就相当于上面那一句了

当删了这句话之后,程序往前跑了一步

此时说明 cur_gdev->gpio_status 的状态根本就是一个空白的数据!!!拿不到数据才会段错误(这个时候才算是真正的发现了出现段错的核心所在了)

---------------------------------------------------------------------------------------------------------------------------------

第六次找:

跟着往上发现是cur_gdev 这个指针有问题

解决思路:

打印该指针的  io状态 、以及 地址(先打印地址,没有地址的话哪来的io状态???

发现该指针的地址为空,这才是发生段错误的真相!根本就拿不到当前指针的地址,剩下的数据也不可能拿到

所以接下来的操作就是看看这个变量会经历什么过程,为什么会没有空间??

此时的核心问题已经转移到该函数 find_gdevice_by_key 上面

因为目前的状态就是该函数根本拿不到数据,打印出来的 cur_dgev 的地址就是一个空

此时就要进一步探讨这个函数的实现逻辑是怎么样的,对比了什么指令,对比指令,传入参数这些是否正确????

-------------------------------------------------------------------------------------------------------------------------------

第七次找:

打印 find_gdevice_by_key 的比对结果是怎么样的

发现是正常的结果

此时就要使用 gdb 调试,找到这个函数 打断点

多文件多函数打断点的方法 break myFile.c:myFunction 

得把其他的线程注释掉来调试

解决思路:

此时考虑 find_gdevice_by_key 的主要功能,在这个函数进行打印调试

发现也是正确的

除此之外还进行了其他的调试

没办法这些也不是最主要的点

第八次找:

考虑一件事(最原始的问题,最初的问题),为什么是开机就会发生段错误???

打开客厅灯不会发生段错误,为什么就开机会发生段错误???

解决思路:

这时候灵光一现!“你说声音会不会是一种设备?作为指令传入到被控设备链表之中”

此时添加 voive_gfevice 文件

奇迹的出现!真的没有报错了

至此,问题得到了解决,就是没有把声音当作一个设备,进行传入到当前的设备链表之中,所以造成了只有开机的时候才会发生段错误,因为没有添加开机设备的指令的时候,此时开机就没有指令传到被控链表之中,而find_gdevice_by_key 这个函数只会到当前已加入的设备链表中比对发送的指令,自然也就比对不到声音发过来的0x40这样一个指令,所以就会报错!

========================================================================

更新于第二天:

问题的核心其实还是cur_gdevice为空,但是还是要补充

其实上面的解决的bug只能够解决一时,真正想让项目运行起来的是解决办法是

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/573100.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文笔记:Retrieval-Augmented Generation forAI-Generated Content: A Survey

北大202402的RAG综述 1 intro 1.1 AICG 近年来,人们对人工智能生成内容(AIGC)的兴趣激增。各种内容生成工具已经精心设计,用于生产各种模态下的多样化对象 文本&代码:大型语言模型(LLM)…

抖音短视频矩阵系统源代码开发部署/SaaS贴牌/源码开源

抖音短视频矩阵系统的源代码开发部署可以分为以下几个步骤: 确定需求:首先,你需要确定你想要开发的具体功能和特性,比如用户注册、上传短视频、评论等。 开发源代码:根据需求,你可以选择使用合适的编程语言…

深入理解element-plus table二次封装:从理论到实践的全面指南

前言 在许多中后台管理系统中,表格占据着半壁江山,如果使用element plus组件库,那么少不了要用到table组件,可是table组件的功能过于基础,因此,我在table组件的实现基础之上进一步封装,从而实现…

装饰器模式实战运用(功能增强)

目录 前言 装饰器模式与代理模式的区别 UML plantuml 类图 实战代码 mybatis cache 前言 装饰器模式和代理模式在使用上很相似,都是在不修改原始类代码的情况下,动态地给真实对象的方法做增强。 装饰器模式是通过创建一个包装对象来包裹原有对象…

Vue时间组件:Dayjs与Moment对比

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

python opencv稍基础初学

傅里叶变换 傅里叶变换f​​​​​傅里叶分析之掐死教程(完整版)更新于2014.06.06 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/19763358 相当nice 傅里叶变换的作用 高频:变化剧烈的灰度分量,例如边界 低频:变…

Centos 配置JDK和Tomcat(新手版)

Centos 配置JDK和Tomcat(新手版) 1、安装JDK 如果原环境有jdk则需要卸载。 先用命令查看 rpm -qa|grep java 如果有jdk则需要卸载rpm -e --nodeps java-1.7.0-openjdk-1.7.0.191-2.6.15.5.el7.x86_64rpm -e --nodeps java-1.8.0-openjdk-…

AugmentedReality之路-显示隐藏AR坐标原点(3)

本文介绍如何显示/隐藏坐标原点,分析AR坐标原点跟手机的位置关系 1、AR坐标原点在哪里 当我们通过AugmentedReality的StartARSession函数打开AR相机的那一刻,相机所在的位置就是坐标原点。 2、创建指示箭头资产 1.在Content/Arrow目录创建1个Actor类…

【旅游景点项目日记 | 第一篇】项目服务架构、数据库表设计

Gitee仓库地址:travel-server:景点旅游项目服务端 文章目录 1.项目服务架构2.数据库设计2.1用户服务—travel_ums2.1.1 ums_user—用户表 2.2景点服务—travel_ams2.2.1 ams_attraction—景点表1.2.2 ams_resource_type—资源类型表 2.3票务服务—trabel…

最优算法100例之09-数组中单独出现两次的数字

专栏主页:计算机专业基础知识总结(适用于期末复习考研刷题求职面试)系列文章https://blog.csdn.net/seeker1994/category_12585732.html 题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 题解报告 最优解…

如何使用 ArcGIS Pro 自动矢量化水系

对于某些要素颜色统一的地图,比如电子地图,可以通过图像识别技术将其自动矢量化,这里为大家介绍一下 ArcGIS Pro 自动矢量化水系的方法,希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的电子地图数据&#…

微软正在改进其AI驱动的Copilot在Microsoft Teams中的工作方式,为会议聊天、总结等引入了新的召唤助手方式

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…