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

news2024/12/24 0:02:07

前言

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

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

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

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

有时候又没有段错误

找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.coloradmin.cn/o/1549863.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue使用el-statistic和el-card显示大屏中的统计数据

​ 一、页面内容&#xff1a; <el-row :gutter"20"><el-col :span"6"><el-card class"box-card"><div><el-statisticgroup-separator",":precision"2":value"value2":title"tit…

机器人寻路算法双向A*(Bidirectional A*)算法的实现C++、Python、Matlab语言

机器人寻路算法双向A*&#xff08;Bidirectional A*&#xff09;算法的实现C、Python、Matlab语言 最近好久没更新&#xff0c;在搞华为的软件挑战赛&#xff08;软挑&#xff09;&#xff0c;好卷只能说。去年还能混进32强&#xff0c;今年就比较迷糊了&#xff0c;这东西对我…

JavaEE:网络原理——协议(应用层+传输层)

应用层 协议就是一种约定 应用层&#xff1a;对应应用程序&#xff0c;是程序员打交道最多的一层&#xff0c;调用系统提供的网络api写出的代码都是属于应用层的。应用层有很多现成的协议&#xff0c;但程序员一般用的还是自定义协议 自定义协议要约定好哪些内容&#xff1f…

【pytest、playwright】多账号同时操作

目录 方案实现思路&#xff1a; 方案一&#xff1a; 方案二&#xff1a; 方案实现思路&#xff1a; 依照上图所见&#xff0c;就知道&#xff0c;一个账号是pytest-playwright默认的环境&#xff0c;一个是 账号登录的环境 方案一&#xff1a; 直接上代码&#xff1a; imp…

Unity学习笔记 9.2D射线

下载源码 UnityPackage 1.Ray2D 让小球向右发射射线&#xff1a; Ray2D ray;void Start() {// Ray2D(起点&#xff0c;终点)ray new Ray2D(this.transform.position, Vector2.right);// Debug.DrawLine(起点&#xff0c;终点&#xff0c;颜色&#xff0c;显示时间)Debug.DrawL…

视图的作用

目录 视图的作用 创建视图 为 scott 分配创建视图的权限 查询视图 复杂视图的创建 视图更新的限制问题 更新视图中数据的部门编号&#xff08;视图的存在条件&#xff09; 限制通过视图修改数据表内容 创建只读的视图 复杂视图创建 oracle从入门到总裁:​​​​​​h…

阿里云ECS选型推荐配置

本文介绍构建Kubernetes集群时该如何选择ECS类型以及选型的注意事项。 集群规格规划 目前在创建Kubernetes集群时&#xff0c;存在着使用很多小规格ECS的现象&#xff0c;这样做有以下弊端&#xff1a; 网络问题&#xff1a;小规格Worker ECS的网络资源受限。 容量问题&…

网络链路层之(1)基础概念

网络链路层之(1)基础概念 Author: Once Day Date: 2024年3月27日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: 通信网络技术_Once-Day的博客-CSD…

Fastjson配置消息转换器(时间格式问题)

问题&#xff1a; 我们可以看见&#xff0c;日期的格式有点问题。 由于ArticleListVO类的createTime成员变量是Date类型&#xff0c;默认是由java的Jackson来处理&#xff0c;使用 ISO-8601 规范来处理日期时间格式。ISO-8601 是一种国际标准的日期时间表示法&#xff0c;例如&…

『Apisix安全篇』探索Apache APISIX身份认证插件:从基础到实战

&#x1f680;『Apisix系列文章』探索新一代微服务体系下的API管理新范式与最佳实践 【点击此跳转】 &#x1f4e3;读完这篇文章里你能收获到 &#x1f6e0;️ 了解APISIX身份认证的重要性和基本概念&#xff0c;以及如何在微服务架构中实施API安全。&#x1f511; 学习如何使…

【Git篇】复习git

文章目录 &#x1f354;什么是git⭐git和svn的区别 &#x1f354;搭建本地仓库&#x1f354;克隆远程仓库&#x1f6f8;git常用命令 &#x1f354;什么是git Git是一种分布式版本控制系统&#xff0c;它可以追踪文件的变化、协调多人在同一个项目上的工作、恢复文件的旧版本等…

金蝶BI方案治好我的数据分析困难症

结构分析、趋势分析、分布分析、对比分析……这还是大方向的&#xff0c;细分下来还会根据数据类型和具体场景不同而不同&#xff0c;不仅如此&#xff0c;每个月的数据分析需求还可能不同&#xff0c;导致分析量多且复杂&#xff0c;加班加点也忙不过来。但金蝶BI方案就不一样…

servlet开发详解

一、什么是servlet&#xff0c;干什么用的&#xff1f;&#xff1f;&#xff1f; tomcat作为一个web服务器&#xff0c;也称作servlet容器。servlet只有放在web服务器中才能运行&#xff0c;不能独立运行。tomcat这个容器要做三件事&#xff1a;接收请求、处理请求和响应请求。…

VMware ESXi部署macOS Monterey

正文共&#xff1a;1024 字 30 图&#xff0c;预估阅读时间&#xff1a;2 分钟 最早使用黑苹果是在2015年&#xff0c;装在了古老的Acer商务本上&#xff08;老樹發新芽&#xff0c;acer tm 4750g裝黑蘋果&#xff09;&#xff1b;上次安装黑苹果是在两年前&#xff08;VMware…

uniapp写小程序如何实现分包

众所众知小程序上传的过程中对包的大小有限制&#xff0c;正常情况下不允许当个包超过2M&#xff0c;所以需要分包 需要再pages.json这个文件夹中进行配置 "pages": [{"path": "pages/index/index","style": {"navigationBarTit…

【Flink架构】关于FLink BLOB的组织架构:FLIP-19: Improved BLOB storage architecture:官网解读

文章目录 一. BlobServer架构1.BlobClient2. BlobServer3. BlobCache4. LibraryCacheManager 二、BLOB的生命周期1. 分阶段清理2. BlobCache的生命周期3. BlobServer 三、文件上下载流程1. BlobCache 下载2. BlobServer 上传3. BlobServer 下载 四. Flink中支持的BLOB文件类型1…

VTK 示例 基本的流程-事件交互、球体、

流程可以总结如下&#xff1a; 导入所需的头文件&#xff1a; 首先&#xff0c;导入了一系列 VTK 头文件&#xff0c;这些文件包含了所需的类和函数声明。 创建对象&#xff1a; 创建了两个球体&#xff08;一个较大&#xff0c;一个较小&#xff09;&#xff0c;一个平面&…

Docker和 Containerd 的区别

自 Docker 开启了使用容器的爆发式增长&#xff0c;有越来越多的工具和标准来帮助管理和使用这项容器化技术&#xff0c;与此同时也造成了有很多术语让人感到困惑。 容器生态系统 容器生态系统是由许多令人兴奋的技术、大量的专业术语和大公司相互争斗组成的。 幸运的是&…

Windows平台cmake编译QT源码库,使用VScode开发QT

不愿意安装庞大的QT开发IDE&#xff0c;可以编译QT源码库。 下载源码可以用国内镜像&#xff0c;如清华大学的&#xff1a;Index of /qt/archive/qt/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 我用的是 6.5.3&#xff0c;进去之后&#xff0c;不要下载整个源…

linux环境gitlab迁移到新服务器

目录 备份项目备份gitlab配置阿里云磁盘格式化准备 最近服务器中了挖矿病毒&#xff0c;清理几次&#xff0c;都没有搞定&#xff0c;只能重新安装gitlab 备份项目 先把项目备份到本地 git pull git remote prune origin确保本地代码是最新的并且拥有所有的分支 git remote …