嵌入式软件bug分析基本要求
摘要:软件从来不是一次就能完美的,需要以包容的眼光看待它的残缺。那问题究竟为何产生,如何去除呢?
1、软件问题从哪来
软件缺陷问题千千万万,主要是需求、实现、和运行环境三方面。
1.1 需求描述偏差
客户角度的描述,在经过业务对接、产品经理的转述,最终呈现的软件需求可能已经偏离了原始的述求,开发人员基于自身经验的理解偏差,开发过程缺乏有效的沟通及监督,导致最终的软件功能与客户的核心诉求存在偏差。
1.2 异常处理机制不完善
嵌入式软件必定是运行在特定的硬件设备,硬件本身或环境问题等特殊干扰,开发人员因经验不足缺乏风险评估,面对电脑是无法全方位猜测、模拟各种异常环境下的差异,最终导致设备在特定场景下运行异常。
1.3 软件开发能力不足
嵌入式系统的复杂度与开发人员的能力矛盾,导致软件本身的逻辑存在缺陷。
2、软件开发与软件问题
关于软件bug的来源,排除不可控的外界因素,与软件开发人员相关,或者开发人员可以减少问题的发生的可能,从软件开发角度解决的方案如下:
2.1 重视需求分析
软件开发就是写程序,并设法使之运行,这是个错误的想法。软件结果与客户期望不一致,需求问题不全是软件开发的锅。大多数情况下客户的原始述求不会直接到软件开发,软件开发没法去反诉找客户确认,只能通过软件的实现形式去甄别不合理的,或者针对客观环境、研发团队的基础去评估风险。
比如客户要求可以设备可以定时1秒采集一次温度,精度要求0.0001摄氏度;或者要求数据采集持续采集24h后,每天12:00准点TCP上报后台服务器。这就需要考虑温度传感器的精度、RTC唤醒以及TCP联网时间、24小时采样数据的存储。如果硬件资源或者客观环境无法实现,盲目承诺客户,或者开始编码,最终结果可想而知。
软件开发是个人的任务,但开发前多沟通确认,进行风险评估反馈,减少开发的无用功,也是对开发人员的基本要求。
2.2 积累行业经验
嵌入式产品都是针对某个细分行业,见多识广,才能预判可能出现的异常,开发阶段有针对性的去处理,或者提前告知使用者去规避。有时候经验比技术能力重要。
2.3 提高开发水平
软件开发水平,首先是个人能力,熟悉软件SDK的应用,相关的操作系统、设计模式、调试方法等。软件开发能力大多数情况下决定软件质量和可维护性,这是个长期学习提高的过程,如果一定要提供捷径,那就是多阅读优秀的开源代码。
2.4 先设计再编码
软件开发不能随心所欲,先明确方案和大概的实现流程,胸有成竹,然后再开始编码,完善细节。这理论没毛病,但真正执行起来却比较难,大多数情况下都只在乎软件出结果,而实际上方案不合理,后期修修补补更浪费时间。如果制度和时间不允许,个人在纸上画画框图和结构,先构思再开发也能弥补,起码不至于南辕北辙。
2.5 编码规范
编码规范是软件开发团队合作的标准,嵌入式行业可以参考“华为技术C语言编程规范”,但实际开发过程,和前面的先设计再编码一样,各种不可控因素,比如项目进度压力和开发者水平与认知的差异,导致有编码规范却无法严格执行。随着软件工程规模的扩大,软件交期、代码同步、重构或交接,其风险也逐渐放大。存在编码规则并不能解决问题,只有强制执行才有意义。
2.6 代码缺陷静态检查与单元测试
软件质量是项目成败的关键点之一,在开发周期有限,人力资源不足的情况下,使用工具实现代码自动扫描,分析出潜在隐患点,可从源头减少软件bug,比如cppCheck、PC-lint等,实现代码自动静态分析,或者人工视检,有效规避简单的软件风险。
如果可能,最佳的选择是单元测试,单元测试比可交付成果本身更重要,文档注释不全时,单元测试就是设计文档;单元测试定义的API和用法,以及可能的使用风险点,就是最佳的参考范例;不足100%的覆盖率就是玩忽职守,开发人员应该全权负责测试自己造出的产品。依靠后期的黑盒测试发现问题,其消耗的人力物力,是编写单元测试的几倍,而且单元测试可以反复的自动测试。不过这种情况更多的是存在于开发理论中。可以参考微信公众号 嵌入式系统 的《代码的保养》第二章。
3、前期减少问题
软件问题的解决,有些不是个人能解决的,需要协调沟通,或者与研发团队的整体风格、制度有关。个人能决定的是软件具体逻辑,这也是体现个人技术能力的重点。
3.1 C语言基础
1、多看优秀代码,学习其技巧。
2、使用带参数检测的接口,比如优先选择snprintf,少用sprintf,其它str前缀的如strncmp也是,但要明白这类接口和memcmp区别。不同的编译器表现不一致,平时也要多关注。
在GCC中编译运行(设备):
char str[5];int ret = snprintf(str, 3, "%s", "abcdefg");//ret = 7 ,str = abchar str[99];int ret = snprintf(str, 99, "%s", "abcdefg");//ret = 7 ,str = abcdefg
注:snprintf的返回值为字符串的长度,且写入的字符串后面带有‘\0’结束符。
在VC中编译运行:
char str[5];int ret = snprintf(str, 3, "%s", "abcdefg");//ret = -1 ,str = abc [后面不会自动补\0结束符]
3、注意函数返回类型,避免类型强制转换导致调用判断异常,有些编译器对隐示类型转换直接报错,因为它确实存在风险。
4、合理的使用sizeof、struct、union、weak等关键字,增加代码的可读性和可扩展性。
5、参数使用前,如数组小标,指针变量使用前必须先判断是否合法。
6、浮点数不能直接进行==和!=比较,等等,这些细节太多,可以参考《C陷阱与缺陷》。
7、讲的都会,说的都对,但真实际写代码,就容易各种小问题,主要还是态度问题,缺乏自我检查、自测的步骤,依靠测试发现bug去驱动研发调试修复是大忌。
3.2 动态内存
1、尽量做到申请与释放在同一个函数,申请内存后,先判断是否申请成功,再进行其它操作。
2、内存申请与释放之间有特殊情况return,要注意释放。
3、释放结构体指针前,注意该变量内部是否还有指针变量动态申请空间,先释放内部,再释放外部。
4、关于内存申请与释放,或使用越界是C语言的劣势,如果设备堆空间足够大,可以在申请时额外多申请固定空间,记录申请函数、长度、并在首尾标记,后续释放时检查内存区首尾标记是否被覆盖;或者查询是哪些函数申请的内存始终没有被释放。具体实现方案请关注微信公众号 嵌入式系统 的相关文章。
3.3 跨平台问题
1、使用系统API前先判断自身传入参数的有效性和范围等是否符合要求,一般系统API是库文件,使用错误更难发现问题。
2、针对不同的平台常用的接口,务必增加适配层隔离,便于调试和后续移植。比如有的平台中断(SDK提供的中断回调不一定是硬件中断)不支持串口日志。
3.4 RTOS系统特性
1、多任务的竞争,在RTOS系统中,需要注意全局函数、全局变量的使用,避免互相竞争影响,对公共函数尽量做到可重入设计,具体实现方案请关注微信公众号 嵌入式系统 的《基于RTOS的软件开发理论》 。
2、中断与任务的调度关系 请关注微信公众号 嵌入式系统 的《基于RTOS的软件开发理论》。
3、合理分配任务栈空间和消息队列的深度,函数内部尽量少用大数组。
3.5 个人素养
软件编码完成,不是能编译就收工了,其功能是否符合预期,开发人员自己检查是最高效的,很多问题都是开发不仔细,或者很简单的C基础应用错误,这不是技术问题而是心态。可以多看看开源代码,或者《C专家编程》等。
4、后期解决问题
如果软件问题不可避免,该如何去修复解决呢?
一般来说100%出现的问题都比较容易解决,找到相关代码仔细检查或者加点日志就能发现问题。难处理的是小概率出现的问题,稳定复现它就是成功的一半。
4.1 问题复现
稳定复现问题才能快速对问题进行定位、解决以及验证,如何提高复现的概率?
1、模拟复现条件,问题只在特定的条件下出现,对于依赖外部输入的条件难以满足,可以考虑程序里预设直接进入对应状态,或者软件内部进行极端的压力测试。
2、提高相关代码执行频率,进行某个操作才可能出现异常,人工持续操作,或者软件频繁执行相应的功能,提高问题点的执行频率,加快复现速度。
3、增大测试样本量 ,个别样机难出现,如果条件允许,可以使用多个设备同时进行测试。一般情况下试产就是为了发现这类问题。
4.2 问题定位
缩小排查范围,确认引入问题的函数或代码片段。
1、打印日志 ,日志是最直接、简单的调试方法,在问题的可疑点增加日志输出,以此来追踪程序执行流程以及关键变量的值,观察是否与预期相符。
2、版本回退,使用版本管理工具时可以通过不断回退版本,验证前面版本的情况,定位首次引入该问题的版本,针对该版本的改动进行排查。
3、二分注释,“二分注释”类似二分查找法的方式注释掉部分代码,以此判断问题是否由注释掉的这部分代码引起。具体为将与问题不相干的部分代码注释掉一半,看问题是否解决,未解决则注释另一半,如果解决则继续将注释范围缩小一半,以此类推逐渐缩小问题的范围,确定是哪一块代码导致这个问题。
4、硬件协助,借助示波器、逻辑分析仪分析波形,必要时也请硬件协助分析;问题样机与正常样机的主控对调,看问题是否随芯片走。尤其是涉及驱动方面的问题,比如充电、中断、复位、外设通信调试异常时。
5、仿真调试 ,在线调试可以起到和打印LOG类似的作用,适合排查程序崩溃类的BUG,当程序陷入异常中断候可以直接STOP查看call stack以及内核寄存器的值,快速定位问题点,不过这需要硬件支持。
6、三板斧,使用最多的是前面三种方法,这三板斧足以应付大部分业务逻辑问题;偶尔请硬件协助解决驱动问题,日常开发中的问题都能解决。个别系统层面或者架构不合理导致的深沉问题,要么花时间死磕coredunmp,要么联系原厂FAE协助,一般芯片方案商都提供技术支持。
4.3 问题修复与回归测试
1、缩小范围确定问题代码,再排查具体的函数,修复问题点
2、有些问题属于架构层面,比如和RTOS相关的竞争关系,这种就无法定位到具体问题代码点,只能在宏观上依靠经验或操作系统理论去解决
3、解决后需要进行回归测试,确认问题是否不再出现,也要确认修改不会引入其他新问题。
4.4 复盘
1、一般情况下最后发现原因都是很简单的几句话,比如数据越界或者循环体多执行一次,看起来都是很简单的基础用法,因为一句错误可能需要几周时间来发现解决,为什么当初写错而且没检查发现呢?
2、总结问题产生的原因及解决方法,今后如何防范,对其他平台否值得借鉴,做到举一反三,从失败中吸取经验。
5、心得
业务指示开发、测试驱动开发,这一荒谬方法论,体现在部门合作与职责不清,整体就是效率低下、互相推诿,在这样的环境下开发软件也很累。
相关文章:

嵌入式软件bug分析基本要求
摘要:软件从来不是一次就能完美的,需要以包容的眼光看待它的残缺。那问题究竟为何产生,如何去除呢? 1、软件问题从哪来 软件缺陷问题千千万万,主要是需求、实现、和运行环境三方面。 1.1 需求描述偏差 客户角度的描…...

【C/C++ 17】继承
目录 一、继承的概念 二、基类和派生类对象赋值转换 三、继承的作用域 四、派生类的默认成员函数 五、继承与友元 六、继承与静态成员变量 七、菱形继承与虚拟继承 一、继承的概念 继承是指一个类可以通过继承获得另一个类的属性和方法,扩展自己的功能&…...
解决Linux Shell脚本错误:“/bin/bash^M: bad interpreter: No such file or directory”
在Linux系统中运行Shell脚本时,你可能会遇到一个常见的错误,错误信息如下: -bash: ./xxx.sh: /bin/bash^M: bad interpreter: No such file or directory这个错误通常是由于Shell脚本文件中存在不兼容的换行符引起的。在Windows系统中&#…...

idea创建spring项目
一、环境 window10 IDEA 2022.2.3 maven-3.8.6 二、创建spring项目 1、新建Maven项目 File -> New -> Project 然后如下图选中Maven Archetype,在Archetype,选中maven-archetype-webapp,点击Create 2、配置maven 默认是使用IDEA内…...

【UE 材质】扇形材质
目录 效果 步骤 (1)控制扇形的弧宽度 (2)控制扇形的角度 (3)完整节点 效果 步骤 (1)控制扇形的弧宽度 创建一个材质,混合模式设置为“Additive”,着色…...
【react native】ScrollView的触摸事件与TouchableWithoutFeedback的点击事件冲突
需求背景 使用 ScrollView 组件实现轮播图效果,该轮播图可以自动向右滑动。有下面两个需求: (1)希望用户左右点击的时候,视图可以向左/向右滚动; (2)希望用户触摸在屏幕的时候&am…...

鸿蒙内核框架
1 内核概述 内核简介 用户最常见到并与之交互的操作系统界面,其实只是操作系统最外面的一层。操作系统最重要的任务,包括管理硬件设备,分配系统资源等,我们称之为操作系统内在最重要的核心功能。而实现这些核心功能的操作系统模…...

幻兽帕鲁专用服务器,多人游戏(专用服务器)搭建
玩转幻兽帕鲁服务器,阿里云推出新手0基础一键部署幻兽帕鲁服务器教程,傻瓜式一键部署,3分钟即可成功创建一台Palworld专属服务器,成本仅需26元,阿里云服务器网aliyunfuwuqi.com分享2024年新版基于阿里云搭建幻兽帕鲁服…...

7000字详解Spring Boot项目集成RabbitMQ实战以及坑点分析
本文给大家介绍一下在 Spring Boot 项目中如何集成消息队列 RabbitMQ,包含对 RibbitMQ 的架构介绍、应用场景、坑点解析以及代码实战。 我将使用 waynboot-mall 项目作为代码讲解,项目地址:https://github.com/wayn111/waynboot-mall。本文大…...

AJAX-认识URL
定义 概念:URL就是统一资源定位符,简称网址,用于访问网络上的资源 组成 协议 http协议:超文本传输协议,规定浏览器和服务器之间传输数据的格式;规定了浏览器发送及服务器返回内容的格式 协议范围…...

国图公考:公务员面试资格复审需要准备什么?
参加国考面试的考生在资格审核阶段需要准备以下材料: 1、本人身份证、学生证或工作证复印件。 2、公共科目笔试准考证复印件。 3、考试报名登记表。 4、本(专)科、研究生各阶段学历、学位证书(应届毕业生没有可以暂时不提供)。 5、报名资料上填写的各类证书材料…...

爬虫实战--人民网
文章目录 前言发现宝藏 前言 为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。当然,如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚,文章中如果有记录错误,欢迎读者朋友们…...
【Arduino】LGT8F328 UNO R3编译上传
LGT8F328 UNO R3编译上传 示例代码 这是一段示例代码,将示例代码编译打包上传到LGT8F328 UNO R3开发板。 #include <Servo.h> Servo myservo; int pos 0; void setup() {// put your setup code here, to run once:Serial.begin(9600);Serial.println(&qu…...

Python进阶----在线翻译器(Python3的百度翻译爬虫)
目录 一、此处需要安装第三方库requests: 二、抓包分析及编写Python代码 1、打开百度翻译的官网进行抓包分析。 2、编写请求模块 3、输出我们想要的消息 三、所有代码如下: 一、此处需要安装第三方库requests: 在Pycharm平台终端或者命令提示符窗口中输入以下代…...

ArcGISPro中Python相关命令总结
主要总结conda方面的相关命令 列出当前活动环境中的包 conda list 列出所有 conda 环境 conda env list 克隆环境 克隆以默认的 arcgispro-py3 环境为模版的 my_env 新环境。 conda create --clone arcgispro-py3 --name my_env --pinned 激活环境 activate my_env p…...

2024年混合云:趋势和预测
混合云环境对于 DevOps 团队变得越来越重要,主要是因为它们能够弥合公共云资源的快速部署与私有云基础设施的安全和控制之间的差距。这种环境的混合为 DevOps 团队提供了灵活性和可扩展性,这对于大型企业中的持续集成和持续部署 (CI/CD) 至关重要。 在混…...

c++入门学习④——对象的初始化和清理
目录 对象的初始化和清理: why? 如何进行初始化和清理呢? 使用构造函数和析构函数编辑 构造函数语法: 析构函数语法: 构造函数的分类: 两种分类方式: 三种调用方法: 括号法(默认构造函数调用&…...
Java-spring注解的作用
1.Qualifier:通常与Autowired搭配使用,通过指定具体的beanName来注入相应的bean 当容器中有多个类型相同的Bean时,可以使用Qualifier注解来指定需要注入的Bean。Qualifier注解可以用于字段、方法参数、构造函数参数等位置 Service public cl…...

Allegro如何把Symbols,shapes,vias,Clines,Cline segs等多种元素一起移动
Allegro如何把Symbols,shapes,vias,Clines,Cline segs等多种元素一起移动 在用Allegro进行PCB设计时,有时候需要同时移动某个区域的所有元素,如:Symbols,shapes,vias,Clines,Cline segs等元素。那么如何操作呢? 首先就是把Symbols,shapes,vias,Clines,Cline …...
【力扣】罗马数字转整数,哈希集合+模拟
罗马数字转整数原题地址 方法一:模拟 罗马数字是字符串,其中每个字符都对应一个整数值,为了方便查找,可以预先把这种对应关系存储到哈希表中。 遍历字符串,对于每个字符, 如果该字符不是最右边的字符&a…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...