【经验分享】关于静态分析工具排查 Bug 的方法

news2024/9/24 13:24:21

文章目录

  • 编译器的静态分析
  • cppcheck
    • 安装 cppcheck
    • 运行 cppcheck

程序员的日常工作,不是摸鱼扯皮,就是在写 Bug。虽然这是一个梗,但也可以看出,程序员的日常一定绕不开 Bug。而花更少的时间修复软件中的 Bug,且不引入新的 Bug,最好的办法就是使用静态分析工具排查 Bug。

所谓的静态分析,顾名思义,是指在不运行程序的情况下对源代码进行检查,通过算法和模式识别来检测可能存在的错误、漏洞或不符合编码规范的地方。这种方法不仅可以帮助开发者在早期阶段发现 Bug,还能提高代码质量和安全性,减少后期调试的时间和成本。

但是在讨论静态分析工具之前,你知道编译器也进行静态代码分析吗?

编译器的静态分析

编译器的作用,就是生成可执行文件或二进制文件,因此,在默认情况下,编译器并不用于静态代码分析。但随着技术的发展和版本的迭代更新,编译在静态代码分析方面不断改进并变得更好,不同版本的编译器在编译同一个代码时,出现警告数量可能都不一样。

对很多初学者来说,编译器生成的警告非常烦人,并且大多数消息并不关键或不会对应用程序造成任何问题。其实我们应该信任编译器,因为有一件事是肯定的:没有人比编译器本身更了解语言、语法和语义。

那么编译器要怎么进行静态分析呢?

以下面的代码为例,我用不同的编译器进行编译并运行,

#include <stdio.h>

#define ON  0xFF
#define OFF 0x00

void print_message(char status)
{
	if (status == ON)
		printf("ON\n");
	else
		printf("OFF\n");
}

int main()
{
	print_message(ON);

	return 0;
}

这段代码看起来没有任何问题,而且看起来运行后会打印 ON,而实际上却打印 OFF

以 GCC 编译编译运行,结果如下:

在这里插入图片描述

如果源代码是用 Clang 编译器编译,会立刻给我们一个警告:

在这里插入图片描述

[!WARNING]

这是警告的具体意思,是一个整型常数 255 和一个 char 类型的表达式真正进行比较,代码可能存在逻辑上的问题。

可见 Clang 不仅是一个编译器,也是一个非常不错的静态分析工具。当然,这类警告 GCC 也可以发现,不过需要在编译时,加上两个参数 -Wall-Wpedantic。如下图:

在这里插入图片描述

[!NOTE]

-Wall-Wpedantic 的作用是什么?

  1. -Wall 参数告诉 GCC 启用所有非默认的警告选项。这意味着 GCC 将会报告许多常见的编程错误,包括但不限于未使用的变量、可疑的类型转换、可能的除零错误、条件表达式中的常量等。-Wall 可以帮助开发者找到那些可能在编译时没有错误但在运行时会导致问题的代码缺陷。

    例如,以下是一些由 -Wall 开启的警告:

    • uninitialized: 使用未初始化的变量;
    • unused: 定义了但未使用的变量或函数;
    • conversion: 类型转换可能导致数据丢失;
    • pointer-sign: 指针比较中正负符号的差异;
    • format-security: 格式字符串的安全问题;
    • overflow: 数值运算溢出的风险。
  2. -Wpedantic 参数使 GCC 更加严格地遵守标准,它将警告所有不符合 C 或 C++ 标准的代码。这意味着任何与标准不完全一致的语法或行为都会被标记出来,即使这种行为在 GCC 中可能是默认允许的。

    -Wpedantic 主要关注的是标准一致性问题,比如:

    • 使用扩展的语法,如 GNU 特有的语法;

    • 不符合标准的声明或初始化;

    • 未在标准中明确规定的编译器行为;

    • 对于 C++,它还会警告关于 C++11 或更高版本标准中不再推荐的用法;

值得注意的是, -Wpedantic 可能会警告以下情况:

  • 使用 C99 的特性(如复合字面量)在 C89 模式下编译。
  • 在 C++ 中使用 C 风格的字符串或旧的初始化语法。
  • 使用了在标准中没有定义的行为,比如某些类型的隐式转换。

通常,为了最大程度地提高代码质量,开发者会同时使用 -Wall-Wpedantic。这有助于确保代码不仅避免了常见的编程错误,而且也遵循了语言标准,从而提高了代码的可读性和可移植性。

然而,值得注意的是,-Wpedantic 可能会产生大量警告,特别是在处理旧代码或使用了某些非标准但实用的 GNU 扩展时。因此,在实际应用中,开发者可能需要根据具体情况调整警告级别,以避免被过多的警告信息淹没。

由此可见,作为开发者,我们应该注意所有编译器警告。甚至我们需要能够生成更多警告的工具,那种可以分析源代码并发现语言的奇怪结构、潜在问题和不寻常用法的工具。

Clang 和 GCC 在静态分析方面还是比较出色的,但这不是它们的主要作用,这些警告是在编译过程中完成的简单检查的副产品而言。此外,静态代码分析需要大量时间,并且通常不需要每次编译。编译时间对于编译器来说非常重要。在检查代码质量和编译时间之间需要权衡。

正是如此,也促使了静态代码分析工具的产生,这类工具也称为 lint,其中一个开源的静态分析工具 cppcheck,也是本文的主角。

cppcheck

Cppcheck 是 C/C++ 代码的静态分析工具,它提供独特的代码分析来检测错误,并专注于检测未定义的行为危险的编码结构,其中包括以下几个方面的内容:

  • 野指针或悬空指针
  • 除以零
  • 整数溢出
  • 无效的位移操作数
  • 无效转换
  • STL 的无效使用
  • 内存管理
  • 空指针取消引用
  • 越界检查
  • 未初始化的变量
  • 写入常量数据
  • 未使用或重复的代码

Cppcheck 是一个开源项目,目前托管在 Sourceforge 和 GitHub 上,支持 GNU/Linux、Windows 和 Mac OS 操作系统。

安装 cppcheck

安装 cppcheck 的步骤可在 Cppcheck 官网可以找到。

也可以从 Linux 发行版包管理器获取 cppcheck,以 Ubuntu 系统为例,可以运行以下命令来安装 cppcheck:

sudo apt update
sudo apt install cppcheck

如果要使用最新的 cppcheck 版本,则需要下载源代码,编译并安装,过程如下:

wget https://github.com/danmar/cppcheck/archive/1.90.tar.gz
tar xfv 1.90.tar.gz
cd cppcheck-1.90/
make MATCHCOMPILER=yes FILESDIR=/usr/share/cppcheck HAVE_RULES=yes -j4
sudo make MATCHCOMPILER=yes FILESDIR=/usr/share/cppcheck HAVE_RULES=yes install

运行 cppcheck

以下面这段代码为例,代码作用为计算整数数组的所有元素的总和:

#include <stdio.h>

int buf[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

int calc(void)
{
	int result;
	int i;

	for (i = 0; i <= 10; i++)
		result += buf[i];

	return result;
}

int main()
{
	calc();
	return 0;
}

这段代码其实有两处风险,但是 GCC 编译器(版本号为 11.4.0)无法找到这些风险:

在这里插入图片描述

即使加上了 -Wextra-Werror 两个参数,也找不到任何风险:

在这里插入图片描述

[!NOTE]

-Wextra-Werror 的作用是什么?

  1. -Wextra 标志开启了一系列额外的警告,这些警告超出了默认警告的范畴。该参数的目的是捕捉那些可能不易察觉的编程错误,帮助开发者避免未来可能遇到的运行时错误和维护问题。它包含了多个单独的警告标志,涵盖了可能被忽略或不常见的代码问题,包括但不限于以下警告:

    • 使用未初始化的变量;
    • 形参与实参的类型不匹配;
    • 赋值运算符可能被误解为等于运算符;
    • 可能的枚举值溢出;
    • 函数调用的返回值被忽视;
    • 以及其他潜在的代码错误和不良实践。
  2. -Werror 标志的作用是将所有警告视为错误。换句话说,当编译器遇到任何被 -W 标志开启的警告时,它将停止编译过程,就像遇到了一个真正的编译错误一样。这迫使开发者在编译通过之前必须解决所有的警告。

    -Werror 的主要优点是强制执行代码质量标准,确保没有潜在的编程问题遗留到最终的二进制文件中。这在团队开发环境中特别有用,可以确保所有代码都达到一致的高标准。

现在换 Clang 编译器进行编译,同样也无法找到这些风险:

在这里插入图片描述

Clang 编译器也可以使用与 GCC 相同的参数,如下命令:

clang -Wall -Wextra -Werror -Wpedantic main.c -o main

执行命令后,可以找到两个错误:

在这里插入图片描述

但是这两个错误其实是重复的,引起两个错误的原因都是变量 result 未初始化,如果给 result 初始化后,就不会出现这个错误,如下图:

在这里插入图片描述

把程序改回原来的代码,用 cppcheck 检查,结果可以找到这两个错误,如下图:

在这里插入图片描述

除了 Clang 找出来的 result 未初始化之外,cppcheck 还在 for 循环中找到了数组越界。

[!CAUTION]

calc 函数的 for 循环中,使用了 i <= 10 作为循环终止条件,然而数组 buf 的下标是从 0 到 9(共10个元素)。当程序尝试访问 buf[10] 时,这实际上是越界访问,因为 buf[10] 并不存在(数组最后一个元素是 buf[9])。

由此可见,编译器并不能完全充当静态分析工具,逻辑上的错误还是要靠专业的静态分析工具。

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

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

相关文章

第4章 Express路由的深入理解(二)

4 路由分组 路由分组用于将相关的路由组织在一起&#xff0c;使代码更具模块化和可维护性。可以通过使用 express.Router 创建路由组。 示例&#xff1a; const express require(express); const app express(); const apiRouter express.Router(); const userRouter ex…

【青书学堂】2024年第一学期 保险理论与实务(高起专) 作业

【青书学堂】2024年第一学期 保险理论与实务(高起专) 作业 为了方便日后复习&#xff0c;青书学堂成人大专试题整理。 若有未整理的课程&#xff0c;请私信我补充&#xff0c;欢迎爱学习的同学们收藏点赞关注&#xff01;文章内容仅限学习使用&#xff01;&#xff01;&#xf…

debian 实现离线批量安装软件包

前言 实现在线缓冲需要的软件和对应依赖的包&#xff0c;离线进行安装 &#xff0c;用于软件封装。 测试下载一个gcc和依赖环境&#xff0c;关闭默认在线源&#xff0c;测试离线安装gcc和依赖环境 兼容 debian ubuntu/test 测试下载安装包到目录 vim /repo_download.sh #!…

每日练习,不要放弃

目录 题目1.下面叙述错误的是 ( )2.java如何返回request范围内存在的对象&#xff1f;3.以下代码将打印出4.下列类定义中哪些是合法的抽象类的定义&#xff1f;&#xff08;&#xff09;5.以下代码段执行后的输出结果为6.以下代码运行输出的是总结 题目 选自牛客网 1.下面叙述…

几何相关计算

目录 一、判断两个矩形是否相交 二、判断两条线段是否相交 三、判断点是否在多边形内 四、垂足计算 五、贝塞尔曲线 六、判断多边形顺时针还是逆时针 七、判断凹多边形 一、判断两个矩形是否相交 当矩形1的最大值比矩形2的最小值都小&#xff0c;那矩形1和矩形2一定不相…

ollama + fastgpt 搭建免费本地知识库

目录 1、ollama ollama的一些操作命令: 使用的方式: 2、fastgpt 快速部署: 修改配置: config.json: docker-compose.yml: 运行fastgpt: 访问OneApi: 添加令牌和渠道: 登陆fastgpt,创建知识库和应用 3、总结: 附录: 1. 11434是ollama的端口: 2. m3e 测…

SCI成稿丨计算机结合,中三区

Web服务器在慢速DDoS攻xxx改进研究互联网技术下基于xxx智能化交互空间艺术研究智慧城市视角企业经济发展中节xxxxx无线网络遥感图像xxx设计和规划中的应用分析基于智能物联网的生态养老控制系统与xxx展基于心理行为大数据分类算法的心理xxxxxxxxxx终端技术对消费者行为分析及客…

使用llama.cpp量化模型

文章目录 概要整体实验流程技术细节小结 概要 大模型量化是指在保持模型性能尽可能不变的情况下&#xff0c;通过减少模型参数的位数来降低模型的计算和存储成本。本次实验环境为魔搭社区提供的免费GPU环境&#xff08;24G&#xff09;&#xff0c;使用Llama.cpp进行4bit量化可…

go 语言实现快速排序

快速排序 - go 一、思路二、步骤及图解三、代码实现四、复杂度分析 一、思路 快速排序是一种分治策略的排序算法&#xff0c;关键过程是对数组进行划分。选择一个基准值&#xff08;pivot element&#xff09;&#xff0c;围绕着这个基准值划分子数组&#xff0c;对子数组递归调…

CyberVadis认证流程

1. 评估现有安全实践&#xff1a;组织需要对其现有的安全实践进行全面评估&#xff0c;包括安全策略、技术架构、人员安全意识等。 2. 确定目标&#xff1a;根据组织的需求和目标&#xff0c;确定需要改进的领域和优先级。 3. 制定计划&#xff1a;制定详细的认证计划&#x…

在 Windows 上开发.NET MAUI 应用_2.生成你的第一个应用

先决条件 Visual Studio 2022 17.8 或更高版本&#xff0c;并安装了 .NET Multi-platform App UI 工作负载。 可参考上一篇文章&#xff1a;http://t.csdnimg.cn/n38Yy 创建应用 1.启动 Visual Studio 2022。 在开始窗口中&#xff0c;单击“创建新项目”以创建新项目&#…

美式键盘 QWERTY 布局的来历

注&#xff1a;机翻&#xff0c;未校对。 The QWERTY Keyboard Is Tech’s Biggest Unsolved Mystery QWERTY 键盘是科技界最大的未解之谜 It’s on your computer keyboard and your smartphone screen: QWERTY, the first six letters of the top row of the standard keybo…

黑马头条Day02-app端文章查看,静态化freemarker

学习内容&#xff1a; 一、app端文章列表 1. 需求分析 文章的布局展示 2. 导入文章数据库 可以使用IDEA的数据库连接工具执行SQL脚本 3. 表结构分析 ap_article文章基本信息表 ap_article_config文章配置表 ap_article_content文章内容表 把课前资料里提供的实体类复制到mod…

转移C盘中的conda环境(包括.condarc文件修改,environment.txt文件修改,conda报错)

conda环境一般是默认安装到C盘的&#xff0c;若建立多个虚拟环境&#xff0c;时间长了&#xff0c;容易让本不富裕的C盘更加雪上加霜&#xff0c;下面给出将conda环境从C盘转移到D盘的方法。 目录 电脑软硬件转移方法查看当前conda目录转移操作第一步&#xff1a;.condarc文件修…

vmware虚拟机中,Centos安装Docker,解决国内无法访问

背景 本文主要解决了centos 的yum源 无法更新 和 docker的 源 国内无法访问的问题。 本文环境&#xff1a;windows宿主机装了vmware虚拟机&#xff0c;虚拟机中安装了Centos&#xff0c;centos内装docker。其实可以直接在window装docker desktop for windows&#xff0c;但…

ns3-gym入门(三):在opengym基础上实现一个小小的demo

因为官方给的"opengym""opengym-2"这两个例子都很简单&#xff0c;所以自己改了一个demo&#xff0c;把reward-action-state相互影响的关系表现出来 一、准备工作 在ns3.35/scratch目录下创建一个文件夹&#xff1a; &#xff08;后续的运行指令后面都需要…

JVM---对象是否存活及被引用的状态

1.如何判断对象是否存活 1.1 引用计数算法 概念&#xff1a;在对象头部增加一个引用计数器,每当有一个地方引用它时&#xff0c;计数器值就加一&#xff1b;当引用失效时&#xff0c;计数器值就减一&#xff1b;任何时刻计数器为零的对象就是不可能再被使用的。 优点&#xff1…

喰星云·数字化餐饮服务系统 多处 SQL注入漏洞复现

0x01 产品简介 喰星云数字化餐饮服务系统是一款专为餐饮企业设计的综合性管理软件,旨在通过信息化手段提升餐饮企业的运营效率、降低运营成本,并实现数据驱动的决策管理。该系统包括供应链管理、财务管理、巡店管理、人力资源管理等多个模块,可全面覆盖餐饮企业的日常运营需…

【多线程综合】java何时考虑线程安全问题、怎么考虑、又怎么解决?

前言&#xff1a;在编程中&#xff0c;线程安全是一个非常重要的概念。它涉及到多个线程并发访问共享资源时的正确性和一致性。在Java中&#xff0c;为了确保线程安全&#xff0c;我们需要考虑一些关键因素。 1、什么是线程安全 线程安全是指当多个线程同时访问一个对象时&am…

十大排序 之 快速排序

&#xff01;&#xff01;&#xff01;排序仅针对于数组哦本次排序是按照升序来的哦代码后边有图解哦 介绍 快速排序英文名为Quick Sort 基本思路 快速排序采用的是分治思想&#xff0c;即在一个无序的序列中选取一个任意的基准元素base&#xff0c;利用base将待排序的序列分…