【嵌入式】嵌入式系统稳定性建设:静态代码扫描的稳定性提升术

1. 概述

在嵌入式系统开发过程中,代码的稳定性和可靠性至关重要。静态代码扫描工具作为一种自动化的代码质量检查手段,能够帮助开发者在编译前发现潜在的缺陷和错误,从而增强系统的稳定性。本文将介绍如何在嵌入式C/C++开发中使用静态代码扫描工具,并通过示例代码展示其应用效果。

文章目录

  • 1. 概述
  • 2. 静态代码扫描工具简介
  • 3. 使用静态代码扫描工具的步骤
    • 3.1 选择合适的静态代码扫描工具
    • 3.2 配置扫描工具
    • 3.3 集成到开发流程中
    • 3.4 分析和修复问题
  • 4. cppcheck功能演示
    • 4.1 问题代码
    • 4.2 问题1:数组越界
    • 4.3 问题2:变量未初始化val
    • 4.4 问题3:申请的内存未释放
    • 4.5 修复后的代码
  • 5. 总结
  • 6. 高阶玩法

2. 静态代码扫描工具简介

静态代码扫描工具通过对源代码进行静态分析,检查代码中的语法错误、逻辑错误、安全漏洞等问题,并给出相应的警告或错误提示。这些工具可以集成到开发流程中,作为代码提交前的自动检查手段,帮助开发者及时发现问题并进行修复。

3. 使用静态代码扫描工具的步骤

3.1 选择合适的静态代码扫描工具

根据项目的需求和团队的偏好,选择一款适合嵌入式C/C++开发的静态代码扫描工具。常见的工具有Cppcheck、PCLint、Coverity等。

3.2 配置扫描工具

根据不同工具的文档,配置扫描规则、扫描范围等参数,确保工具能够针对项目的特点进行准确的扫描。

3.3 集成到开发流程中

将静态代码扫描工具集成到开发流程中,如持续集成/持续部署(CI/CD)系统中,实现自动化的代码质量检查。这个话题并非本文的核心,后面将使用单独文章来进行讨论。

3.4 分析和修复问题

定期运行扫描工具,分析扫描结果,并根据提示修复代码中的问题。

4. cppcheck功能演示

本文以cppeheck(Ubuntu上的安装命令:sudo apt-get install cppcheck)为例演示静态代码扫描的过程和结果展示。其它工具留待大家自行实验以比较各自的优缺点。

4.1 问题代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>int exampleFunction()
{printf("%s enter\n", __func__);int array[10];int index = 10;array[index] = 42; // 数组越界访问printf("%s leave\n", __func__);return 0;
}int exampleFunction1()
{int value; // 变量未初始化printf("%s enter\n", __func__);if (value == 0) {printf("value is 0");} else {printf("value not 0");}printf("%s leave\n", __func__);return 0;
}int exampleFunction2()
{char *buffer = NULL;printf("%s enter\n", __func__);buffer = malloc(10); //buffer申请的内存没有释放strcpy(buffer, "haha");printf("%s leave\n", __func__);return 0;
}int main(int argc, char *argv[])
{exampleFunction();exampleFunction1();exampleFunction2();return 0;
}

如上所示,代码包含了三个函数:exampleFunctionexampleFunction1exampleFunction2,以及一个 main函数来调用它们。
下面是该程序编译运行的结果:
在这里插入图片描述
可以发现,该程序运行过程中出现了异常,被终止运行了。

实际上,这3个函数每一个函数都有其独特的问题,这些问题就可以通过静态代码扫描工具在编译前发现。下面我将逐一解释每个函数的问题,并展示cppcheck扫描到的结果。

4.2 问题1:数组越界

exampleFunction这个函数试图访问数组 array 的第 11 个元素(索引为 10),但是 array 实际上只有 10 个元素(索引从 09)。这是一个典型的数组越界访问错误

使用cppcheck静态代码扫描工具进行扫描,会得到类似以下的扫描结果:
在这里插入图片描述
结果清晰命令:[example.c:11]: (error) Array 'array[10]' accessed at index 10, which is out of bounds.,翻译过来就是:example.c的11行存在错误:数组array试图访问下标为10的数组元素,这超出了数组的边界

根据扫描结果的提示,我们应该修复数组越界访问的问题。修复方案如下:

  1. 确保数组索引在有效范围内。
  2. 如果需要访问数组的最后一个元素,使用sizeof(array) / sizeof(array[0]) - 1来计算最后一个有效索引。

4.3 问题2:变量未初始化val

exampleFunction1这个函数声明了一个整数变量value,但没有初始化它。然后它检查value是否等于 0,但由于value是未初始化的,这个检查是未定义的,因为它可能包含任何随机值,也就是每次运行可能会进入if分支,也可能会引入else分支,完全是一个随机事件。

使用cppcheck静态代码扫描工具进行扫描,会得到类似以下的扫描结果:
在这里插入图片描述
结果清晰命令:[example.c:24]: (error) Uninitialized variable: value,翻译过来就是:example.c的24行存在错误:未初始化变量:value

根据扫描结果的提示,我们应该修复变量未初始化的问题。修复方案如下:

  1. 在定义所有变量时,确保对其进行初始化。

4.4 问题3:申请的内存未释放

exampleFunction2这个函数分配了10字节的内存给buffer,然后尝试将字符串 "haha"(包括一个终止符 ‘\0’ 总共 5 个字符)复制到buffer中。函数在退出前没有释放分配的内存,导致出现了内存泄漏。

使用cppcheck静态代码扫描工具进行扫描,会得到类似以下的扫描结果:
在这里插入图片描述
结果清晰命令:[example.c:46]: (error) Memory leak: buffer,翻译过来就是:example.c的46行存在错误:内存泄漏:value

根据扫描结果的提示,我们应该修复变量未初始化的问题。修复方案如下:

  1. 确保在不再需要内存时使用free函数释放它。

4.5 修复后的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>int exampleFunction()
{printf("%s enter\n", __func__);int array[10];int index = sizeof(array) / sizeof(array[0]) - 1;array[index] = 42; // 数组越界访问,已经修复printf("%s leave\n", __func__);return 0;
}int exampleFunction1()
{int value = 0; // 变量未初始化,已经修复printf("%s enter\n", __func__);if (value == 0) {printf("value is 0");} else {printf("value not 0");}printf("%s leave\n", __func__);return 0;
}int exampleFunction2()
{char *buffer = NULL;printf("%s enter\n", __func__);buffer = malloc(10); //buffer申请的内存没有释放,已经修复strcpy(buffer, "haha");free(buffer);printf("%s leave\n", __func__);return 0;
}int main(int argc, char *argv[])
{exampleFunction();exampleFunction1();exampleFunction2();return 0;
}

修复后的代码,编译运行结果如下所示,可以看到,所有函数正常执行,使用valgrind检测,也没有内存泄漏了。
在这里插入图片描述

5. 总结

静态代码扫描工具是嵌入式C/C++开发中不可或缺的一部分,它能够帮助开发者及时发现并修复代码中的潜在问题,提高系统的稳定性和可靠性。

6. 高阶玩法

通过集成静态代码扫描工具到开发流程中,并定期对代码进行扫描和修复,我们可以有效地提升嵌入式系统的质量。

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

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

相关文章

排序算法——梳理总结

✨冒泡 ✨选择 ✨插入  ✨标准写法  &#x1f3ad;不同写法 ✨希尔排序——标准写法 ✨快排 ✨归并 ✨堆排 ✨冒泡 void Bubble(vector<int>& nums) {// 冒泡排序只能先确定最右边的结果&#xff0c;不能先确定最左边的结果for (int i 0; i < nums.size(); i){…

基于深度学习的交通标志检测识别系统(含UI界面、yolov8、Python代码、数据集)

项目介绍 项目中所用到的算法模型和数据集等信息如下&#xff1a; 算法模型&#xff1a;     yolov8 yolov8主要包含以下几种创新&#xff1a;         1. 添加注意力机制&#xff08;SE、CBAM等&#xff09;         2. 修改可变形卷积&#xff08;DySnake-主干c…

linux系统命令深入研究1——ls的参数

ls list命令有一些常用的参数&#xff0c;其中-a意为列出all全部文件&#xff08;包括隐藏文件&#xff09;&#xff0c;-l列出详细信息&#xff0c;-h以人类可阅读的方式列出文件大小 --full-time是列出详细时间信息&#xff0c;包括最后一次修改时间 -t是按时间排序&#xff…

Git 内幕探索:从底层文件系统到历史编辑的全面指南

微信搜索“好朋友乐平”关注公众号。 1. Git 底层文件对象 #mermaid-svg-uTkvyr26fNmajZ3n {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-uTkvyr26fNmajZ3n .error-icon{fill:#552222;}#mermaid-svg-uTkvyr26fNmaj…

Spark实战-基于Spark日志清洗与数据统计以及Zeppelin使用

Saprk-日志实战 一、用户行为日志 1.概念 用户每次访问网站时所有的行为日志(访问、浏览、搜索、点击)用户行为轨迹&#xff0c;流量日志2.原因 分析日志&#xff1a;网站页面访问量网站的粘性推荐3.生产渠道 (1)Nginx(2)Ajax4.日志内容 日志数据内容&#xff1a;1.访问的…

【动态规划】完全背包

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;【LeetCode】winter vacation training 目录 &#x1f449;&#x1f3fb;完全背包 &#x1f449;&#x1f3fb;…

政安晨:【深度学习处理实践】(二)—— 最大汇聚运算

最大汇聚运算&#xff08;Max Pooling Operation&#xff09;是深度学习领域卷积神经网络常用的一种汇聚运算方式。在卷积神经网络中&#xff0c;经过一系列卷积层和激活函数层后&#xff0c;数据在空间尺寸上逐渐减小&#xff0c;特征图的深度也逐渐增加。为了降低数据尺寸并提…

微信小程序(五十三)修改用户头像与昵称

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.外界面个人资料基本模块 2.资料修改界面同步问题实现&#xff08;细节挺多&#xff0c;考虑了后期转服务器端的方便之处&#xff09; 源码&#xff1a; app.json {"window": {},"usingCompone…

算法打卡day11|栈与队列篇03|Leetcode 239. 滑动窗口最大值、347.前 K 个高频元素

小顶堆和大顶堆 小顶堆&#xff08;Min Heap&#xff09;和大顶堆&#xff08;Max Heap&#xff09;是两种特殊的完全二叉树&#xff0c;它们遵循特定的堆属性&#xff0c;即父节点的值总是小于或等于&#xff08;小顶堆&#xff09;或者大于或等于&#xff08;大顶堆&#xf…

Latex公式太长换行标号

Latex中公式太长换行&#xff0c;且编号&#xff0c;可以采用align&#xff0c;不编号行公式用\nonumber&#xff0c;示例如下&#xff1a; \begin{align}\nonumber %第1行公式不编号&abababababababa\\&cdm %第2行公式编号 \end{align}效果如下 原文件链接 公式不…

WordPress建站入门教程:如何上传安装WordPress主题?

我们成功搭建WordPress网站后&#xff0c;默认使用的是自带的最新主题&#xff0c;但是这个是国外主题&#xff0c;可能会引用一些国外的资源文件&#xff0c;所以为了让我们的WordPress网站访问速度更快&#xff0c;强烈建议大家使用国产优秀的WordPress主题。 今天boke112百…

【MySQL 系列】MySQL 架构篇

在我们开始了解 MySQL 核心功能之前&#xff0c;首先我们需要站在一个全局的视角&#xff0c;来看 SQL 是如何运作执行的。通过这种方式&#xff0c;我们可以在头脑中构建出一幅 MySQL 各组件之间的协同工作方式&#xff0c;有助于我们加深对 MySQL 服务器的理解。 文章目录 1、…

深入浅出运维可观测工具(四):如何使用eBPF绘制网络拓扑图

哈喽~又到了我们技术分享环节了。eBPF这个系列自分享以来收到了很多朋友的喜欢&#xff0c;真是让博主又惊又喜&#xff0c;感谢大家的支持。话不多说&#xff0c;今天我们将对如何使用eBPF绘制网络拓扑图做一篇分享&#xff0c;文章较长&#xff0c;干货较多&#xff0c;大家可…

R语言lavaan结构方程模型在复杂网络分析中的科研技术新趋势

此外&#xff0c;我们还将深入探讨R语言的基础知识、结构方程模型的基本原理、lavaan程序包的使用方法等内容。无论是潜变量分析、复合变量分析&#xff0c;还是非线性/非正态/缺失数据处理、分类变量分析、分组数据处理等复杂问题&#xff0c;我们都将一一为您解析。 希望通过…

微服务获取登录用户Id与单体服务下获取用户Id对比(黑马头条Day03)

前置声明 当前前后端分离开发项目中&#xff0c;后端某个请求向具体某个数据库中的多个表插入数据时&#xff0c;经常需要使用到当前登录用户的Id&#xff08;唯一标识&#xff09;。在当前用户线程下以实现变量共享&#xff0c;同时为了避免不同用户线程之间操作变量的影响&am…

【机器学习300问】28、什么是决策树?

〇、两个预测任务 &#xff08;1&#xff09;任务一&#xff1a;银行预测偿还能力 当前&#xff0c;某银行正致力于发掘潜在的放贷用户。他们掌握了每位用户的三个关键特征&#xff1a;房产状况、婚姻状况以及年收入。此外&#xff0c;银行还拥有过往这些用户的债务偿还能力的…

蓝桥杯简单题,公司名称

题目链接&#xff08;需要登录&#xff09; #include <iostream> #include <cstring> #include <algorithm> using namespace std; bool lanqiao(string str,int len){ sort(str.begin(),str.end());//对str按照ascii排序if(str.find("Laainoq")s…

React 从0到1构建企业级框架基于Antd Designer

一、 create-react-app 创建 cms-front 二、 删除不必须要的文件形成如下结构 1. React版本为17版本 public 文件夹下保留 favicon.ico 偏爱图标index.html资源文件 2.src 保留 index.js 入口文件和app.js(基于spa原则)单文件即可 三、配置eslint 1. 安装 eslint. npm inst…

DataX及使用

DataX及使用 【一】DataX概述【二】DataX架构原理【1】设计理念【2】框架设计【3】运行流程【4】调度决策思路【5】DataX和Sqoop对比 【三】DataX部署【四】DataX上手【1】使用概述【2】配置文件格式【3】同步Mysql数据到HDFS 【五】DataX整合Springboot 【一】DataX概述 Data…

27.基于springboot + vue实现的前后端分离-网上租赁交易系统(项目 + 论文)

项目介绍 本课题是根据用户的需要以及网络的优势建立的一个基于Spring Boot的网上租贸系统&#xff0c;来满足用户网络商品租赁的需求。本网上租贸系统应用Java技术&#xff0c;MYSQL数据库存储数据&#xff0c;基于Spring Boot框架开发。在网站的整个开发过程中&#xff0c;首…