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

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.hqwc.cn/news/520497.html

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

相关文章

Java面试篇【并发编程】常见面试题(2024最新)

Java并发编程常见面试题 1.什么是线程和进程&#xff1f; 进程是操作系统分配资源的最小单位&#xff0c;各个进程之间占据独立的寻址空间&#xff0c;运行也是独立运行&#xff0c;进程间通信需要一些机制。进程间切换需要的开销较大。 线程是程序执行的基本单位&#xff0c…

Python数据处理实战(4)-上万行log数据提取并作图进阶版

系列文章&#xff1a; 0、基本常用功能及其操作 1&#xff0c;20G文件&#xff0c;分类&#xff0c;放入不同文件&#xff0c;每个单独处理 2&#xff0c;数据的归类并处理 3&#xff0c;txt文件指定的数据处理并可视化作图 4&#xff0c;上万行log数据提取并作图进阶版&a…

Vue中项目使用debugger,浏览器无效!

现象&#xff1a;下载了别的项目&#xff0c;启动之后&#xff0c;打了debugger&#xff0c;结果浏览器居然忽视&#xff0c;直接过去。打一堆日志&#xff0c;太麻烦了。 解决方案 第一步 F12打开浏览器调试器&#xff0c;找到设置 第二步 如果是英文的&#xff0c;找这…

扩展学习|系统理解数字经济

文献来源&#xff1a;[1]肖静华,胡杨颂,吴瑶.成长品&#xff1a;数据驱动的企业与用户互动创新案例研究[J].管理世界,2020,36(03):183-205.DOI:10.19744/j.cnki.11-1235/f.2020.0041. [2]陈晓红,李杨扬,宋丽洁等.数字经济理论体系与研究展望[J].管理世界,2022,38(02):208-22413…

Java毕业设计 基于SpringBoot vue 疫苗咨询与预约系统

Java毕业设计 基于SpringBoot vue 疫苗咨询与预约系统 SpringBoot vue 疫苗咨询与预约系统 功能介绍 用户前端&#xff1a;首页 图片轮播 疫苗信息 条件查询 疫苗详情 点我收藏 评论 接种疫苗 疫情资讯 资讯详情 资讯评论 论坛交流 发布帖子 公告信息 公告详情 留言反馈 登录…

JavaEE之volatile关键字

一.内存可见性问题 什么是内存可见性问题 计算机运行的程序/代码&#xff0c;往往需要访问数据。这些数据往往存在于内存中。 cup使用此变量时&#xff0c;就会把内存中的数据先读出来&#xff0c;加载到cpu寄存器中&#xff0c;再去参与运算。 但是&#xff0c;关键是cpu读…

Uninty 鼠标点击(摄像机发出射线-检测位置)

平面来触发碰撞&#xff0c;胶囊用红色材质方便观察。 脚本挂载到胶囊上方便操作。 目前实现的功能&#xff0c;鼠标左键点击&#xff0c;胶囊就移动到那个位置上。 using System.Collections; using System.Collections.Generic; using UnityEngine;public class c6 : MonoBe…

【自动驾驶系列丛书学习】2.《自动驾驶汽车环境感知》学习笔记

《自动驾驶技术概论》学习笔记 致谢&#xff1a;作者&#xff1a;甄先通、黄坚、王亮、夏添 -------------------------------------------------------------------------------------------------------- 笔记目录 -----------------------------------------------------…

断开服务器仍后台运行程序

1.可以使用nohup命令&#xff1a; nohup python xx.py 2>1& 不要忘记 2>1& 之后会返回一个进程号&#xff08;记不住也没关系&#xff0c;可以看3&#xff09;&#xff0c;此时程序就在后台运行了&#xff0c;与服务器断开连接也能正常运行 2.在终端实时打印…

Kotlin/Java重写equals后==表现(2)

Kotlin/Java重写equals后表现&#xff08;2&#xff09; 如果不重写默认的equals方法&#xff0c;即使用Object默认的equals()方法&#xff0c;而Object默认的equals方法&#xff0c;其实比较两个对象的地址&#xff1a; fun main(args: Array<String>) {val u1 User(&…

关于并发编程和并行

目录 前言: 并发编程: 1.并发编程的定义: 2. 并发编程的目的 2.1提高性能&#xff1a; 2.2增强响应性&#xff1a; 2.3资源利用&#xff1a; 3. 并发编程的实现方式 3.1多线程&#xff1a; 3.2多进程&#xff1a; 3.3异步编程&#xff1a; 3.4协程&#xff1a; 4. …

Java后台面试相关知识点解析

文章目录 JavaJava中四种引用类型及使用场景集合HashMap源码及扩容策略HashMap死循环问题ConcurrentHashMap与HashtableConCurrentHashMap 1.8 相比 1.7 判断单链表是否有环&#xff0c;并且找出环的入口IO线程池线程池的几种创建方式判断线程是否可以回收线程池的7大核心参数线…