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

news2024/11/18 15:26:40

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

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

相关文章

嵌入式学习第二十五天!(网络的概念、UDP编程)

网络&#xff1a; 可以用来&#xff1a;数据传输、数据共享 1. 网络协议模型&#xff1a; 1. OSI协议模型&#xff1a; 应用层实际收发的数据表示层发送的数据是否加密会话层是否建立会话连接传输层数据传输的方式&#xff08;数据包&#xff0c;流式&#xff09;网络层数据的…

Day22:安全开发-PHP应用留言板功能超全局变量数据库操作第三方插件引用

目录 开发环境 数据导入-mysql架构&库表列 数据库操作-mysqli函数&增删改查 数据接收输出-html混编&超全局变量 第三方插件引用-js传参&函数对象调用 完整源码 思维导图 PHP知识点&#xff1a; 功能&#xff1a;新闻列表&#xff0c;会员中心&#xff0…

Python爬虫——scrapy-3

目录 免责声明 任务 文件简介 爬取当当网内容单管道 pipelines.py items.py setting dang.py 当当网多管道下载图片 pipelines.py settings 当当网多页下载 dang.py pielines.py settings items.py 总结 免责声明 该文章用于学习&#xff0c;无任何商业用途 …

深度学习-2.3损失函数

文章目录 损失函数深度学习优化思想回归&#xff1a;误差平方和SSE二分类交叉熵损失函数1. 极大似然函数估计求解二分类交叉熵函数2.用tensor实现二分类交叉熵损失 多分类交叉熵损失函数1.由二分类推广到多分类2.用PyTorch实现多分类交叉熵损失 损失函数 在之前的文章中&#…

OpenAI劲敌吹新风! Claude 3正式发布,Claude3使用指南

Claude 3是什么&#xff1f; 是Anthropic 实验室近期推出的 Claude 3 大规模语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;系列&#xff0c;代表了人工智能技术的一个显著飞跃。 该系列包括三个不同定位的子模型&#xff1a;Claude 3 Haiku、Claude 3…

Chapter20-Ideal gases-CIE课本要点摘录、总结(编辑中)

20.1 Particles of a gas Brownian motion Fast modules 速率的数值大概了解下&#xff1a; average speed of the molecules:400m/s speed of sound:approximately 330m/s at STP&#xff08;standard temperature and pressure&#xff09; Standard Temperature and Pres…

如何使用WinSCP结合Cpolar实现公网远程访问内网Linux服务器

文章目录 1. 简介2. 软件下载安装&#xff1a;3. SSH链接服务器4. WinSCP使用公网TCP地址链接本地服务器5. WinSCP使用固定公网TCP地址访问服务器 1. 简介 ​ Winscp是一个支持SSH(Secure SHell)的可视化SCP(Secure Copy)文件传输软件&#xff0c;它的主要功能是在本地与远程计…

linux上安装fastdfs及配置

一、基础环境准备 1、所需软件 名称说明libfastcommonfastdfs分离出的一些公用函数包fastdfsfastdas软件包fastdfs-nginx-modulefastdfst和nginx的关联模块nginxnginxl软件包 2、编辑环境 安装一些基础的支持环境 yum install git gccc gcc-c make automake autoconf libto…

图遍历算法

图的遍历算法有两种&#xff1a;深度优先遍历、广度优先遍历算法。 深度优先遍历算法就是从起始结点开始&#xff0c;只要有相邻且未被访问的结点就要直接进行访问&#xff0c;直到最后不能向下遍历为止&#xff0c;再回溯寻找下一个策略。 广度优先遍历算法&#xff0c;就是从…

线性代数笔记13--正交向量和正交子空间

0. 四个子空间 1. 正交向量 两向量点乘为0&#xff0c;向量正交。 A ⊤ B 0 A^{\top}B0 A⊤B0 勾股定理 ∣ ∣ x ∣ ∣ 2 ∣ ∣ y 2 ∣ ∣ ∣ ∣ x y ∣ ∣ 2 ||x||^2||y^2||||xy||^2 ∣∣x∣∣2∣∣y2∣∣∣∣xy∣∣2 验证正交条件 ∣ ∣ x ∣ ∣ 2 x ⊤ x x x ⊤ ∣…

vue2【详解】生命周期(含父子组件的生命周期顺序)

1——beforeCreate&#xff1a;在内存中创建出vue实例&#xff0c;数据观测 (data observer) 和 event/watcher 事件配置还没调用&#xff08;data 和 methods 属性还没初始化&#xff09; 【执行数据观测 (data observer) 和 event/watcher 事件配置】 2——created&#xf…

前TVB「御用泼妇」原来是亿万富婆,离婚后狂买楼养大子女。

今年72岁的昔日TVB老戏骨陈曼娜Manna姐最近突然亮相隔壁ViuTV的新剧《飞黄腾达》&#xff0c;本色出演炒股女富豪&#xff0c;她大赞剧集监制、导演有眼光&#xff0c;角色的背景与她本身十分相似&#xff0c;演起来可谓得心应手。 众所周知&#xff0c;陈曼娜最爱「买砖头」&a…

跟无神学AI之Tensorflow笔记搭建网络八股

虽然Pytorch在论文中使用较多&#xff0c;但是像Alphafold在蛋白质结构预测的模型&#xff0c;仍然是用Tensorflow写成&#xff0c;遂近期在学其中的语法。 本系列来自慕课北大软微曹健老师的Tensorflow笔记&#xff0c;摘选其中重要部分。 1.导包 2.定义训练集测试集和数据…

平台工程指南:从架构构建到职责分工

平台工程只是 DevOps 专业化的另一个术语&#xff0c;还是另有所指&#xff1f;事实可能介于两者之间。DevOps 及其相关的 DevXOps 有着浓厚的文化色彩&#xff0c;以各个团队为中心。不幸的是&#xff0c;在许多地方&#xff0c;DevOps 引发了新的问题&#xff0c;如工具激增和…

leetcode 热题 100_三数之和

题解一&#xff1a; 双指针遍历&#xff1a;暴力解法的三层遍历会超时&#xff0c;因此需要优化遍历的过程。首先是需要对结果进行去重&#xff0c;这里采用排序跳过重复值的做法&#xff0c;在指针遍历时跳过已经遍历过的相同值。在第一层循环确定第一个值后&#xff0c;剩下两…

【你也能从零基础学会网站开发】Web建站之HTML+CSS入门篇 常用HTML标签(3)

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享 &#x1f40b; 希望大家多多支持, 我们一起学习和进步&#xff01; &#x1f3c5; 欢迎评论 ❤️点赞&#x1f4ac;评论 &#x1f4c2;收藏 &#x1f4c2;加关注 HTML框架集…

吴恩达机器学习笔记十五 什么是导数 计算图 大型神经网络案例

假设函数 J(w)w^2&#xff0c;当 w3 时&#xff0c; J(w)3*39 当我们给w增加一个很小的量时&#xff0c;观察J(w)如何变化。 例如 w30.001&#xff0c; 则J&#xff08;w&#xff09;9.006001&#xff0c;因此当w3且增加一个变化量 ε 时&#xff0c;J(w)将会增加 6ε&#x…

SpringCloud 微服务架构编码构建

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅&#xff0c;从传统的模块之间调用&#xff0c;一步步的升级为 SpringCloud 模块之间的调用&#xff0c;此篇文章为第一篇&#xff0c;即不使用 SpringCloud 组件进行模块之间的调用&#xff0c;后续会有很多的文章循序渐…

【学习心得】websocket协议简介并与http协议对比

一、轮询和长轮询 在websocket协议出现之前&#xff0c;要想实现服务器和客户端的双向持久通信采取的是Ajax轮询。它的原理是每隔一段时间客户端就给服务器发送请求找服务器要数据。 让我们通过一个生活化的比喻来解释轮询和长轮询假设你正在与一位不怎么主动说话的老大爷&…

软考68-上午题-【面向对象技术2-UML】-事物

一、事物 UML中有4种事物&#xff1a; 结构事物&#xff1b;&#xff08;模型的静态部分&#xff09;行为事物&#xff1b;&#xff08;模型的动态部分&#xff09;分组事物&#xff1b;注释事物。 1-1、结构事物 1-2、行为事物 1-3、分组事物 1-4、注释事物 二、真题 真题1…