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

文章目录

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

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

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

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

编译器的静态分析

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

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

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

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

#include <stdio.h>#define ON  0xFF
#define OFF 0x00void print_message(char status)
{if (status == ON)printf("ON\n");elseprintf("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.mzph.cn/diannao/47305.shtml

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

相关文章

lightgbm

lightGBM 1.sklearn 使用代码 【机器学习基础】XGBoost、LightGBM与CatBoost算法对比与调参 首先&#xff0c;XGBoost、LightGBM和CatBoost都是目前经典的SOTA&#xff08;state of the art&#xff09;Boosting算法&#xff0c;都可以归类到梯度提升决策树算法系列。三个模…

5. JavaSE ——【适合小白的数组练习题】

&#x1f4d6;开场白 亲爱的读者&#xff0c;大家好&#xff01;我是一名正在学习编程的高校生。在这个博客里&#xff0c;我将和大家一起探讨编程技巧、分享实用工具&#xff0c;并交流学习心得。希望通过我的博客&#xff0c;你能学到有用的知识&#xff0c;提高自己的技能&a…

【区块链 + 智慧政务】澳门:智慧城市建设之证书电子化项目 | FISCO BCOS应用案例

2019 年 2 月 27 日&#xff0c;澳门政府设立的澳门科学技术发展基金与微众银行达成合作&#xff0c;通过区块链、人工智能、大数据、 云计算等创新技术&#xff0c;共同推进澳门特区的智慧城市建设与未来型城市发展&#xff0c;提升粤港澳大湾区的科创能力。在澳 门智慧城市建…

【数学建模】高温作业专用服装设计(2018A)隐式差分推导

为方便计算&#xff0c;对区域进行离散化处理&#xff0c;采用隐式差分格式进行离散计算。隐式差分格式如图&#xff1a; 每层材料内部 对第 j j j层材料: 其中&#xff0c; λ j \lambda_j λj​表示第 j j j层的热扩散率&#xff0c; c j c_j cj​表示第 j j j层的比热容…

linux需要熟悉的命令理解记忆

(1)光标插入 (1)一般模式下: i 插入到光标前方 记忆方法:在一般模式下, 光标选中字符, 我们按下 i, 就会插入光标的前方, insert, 表示插队 (2)一般模式下: a 插入到光标后方 记忆方法: 在一般模式下, 光标选中字符,a表示append, 添加或者附加的意思 (3) 如果要在行首或者行…

css实现每个小盒子占32%,超出就换行

代码 <div class"visitors"><visitor class"item" v-for"(user,index) in userArr" :key"user.id" :user"user" :index"index"></visitor></div><style lang"scss" scoped&…

java乱码问题

文章目录 1.eclipse所有修改编码的地方2.io读取文件乱码问题1.读写统一2.转换字符编码&#xff1a; 3.http请求返回乱码 1.eclipse所有修改编码的地方 2.io读取文件乱码问题 1.读写统一 如果文件是以UTF-8编码保存的&#xff0c;那么在读取文件时也应使用UTF-8编码。 2.转换…

Apple Vision Pro 和其商业未来

机器人、人工智能相关领域 news/events &#xff08;专栏目录&#xff09; 本文目录 一、Vision Pro 生态系统二、Apple Vision Pro 的营销用例 随着苹果公司备受期待的进军可穿戴计算领域&#xff0c;新款 Apple Vision Pro 承载着巨大的期望。 苹果公司推出的 Vision Pro 售…

百分点科技签约潍坊市数据产业发展战略合作

近日&#xff0c;潍坊市数据产业发展战略合作签约仪式举行&#xff0c;潍坊市人民政府副市长张震生&#xff0c;潍坊市财政局党组书记、局长王金祥&#xff0c;潍坊市大数据局党组书记陈强出席大会并致辞。百分点科技受邀进行战略合作签约&#xff0c;共同见证潍坊市数据要素市…

生成式人工智能(AI)的未来

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

深度学习模型快速开发平台推荐

前言 本文面向深度学习初学者或者工程师&#xff0c;推荐几个常用的深度学习模型快速开发平台。可以帮助初学者快速跑通模型&#xff0c;帮助工程师快速对模型进行部署和应用。 huggingface 简介 不多介绍&#xff0c;全球最大的模型托管平台&#xff0c;该平台最大的特点是…

全网超详细Redis主从部署(附出现bug原因)

主从部署 整体架构图 需要再建两个CentOs7,过程重复单机部署 http://t.csdnimg.cn/zkpBE http://t.csdnimg.cn/lUU5gLinux环境下配置redis 查看自己ip地址命令 ifconfig 192.168.187.137 进入redis所在目录 cd /opt/software/redis cd redis-stable 进入配置文件 vim redi…

JavaWeb入门程序解析(Spring官方骨架、配置起步依赖、SpringBoot父工程、内嵌Tomcat)

3.3 入门程序解析 关于web开发的基础知识&#xff0c;我们可以告一段落了。下面呢&#xff0c;我们在基于今天的核心技术点SpringBoot快速入门案例进行分析。 3.3.1 Spring官方骨架 之前我们创建的SpringBoot入门案例&#xff0c;是基于Spring官方提供的骨架实现的。 Sprin…

勘测院如何实现可控便捷的图纸安全外发?

勘测院&#xff0c;也称为勘测设计研究院或勘测设计院&#xff0c;是进行与地质、地形和地貌有关的勘察测量的单位&#xff0c;为各类工程项目提供准确的地质数据和设计依据。 勘测院会产生各类包括图纸在内的文件&#xff0c;如&#xff1a; 1、项目相关文件&#xff1a;项目…

c++模板初阶----函数模板与类模板

目录 泛型编程 函数模板 函数模板的概念 函数模板的格式 函数模板的原理 函数模板的实例化 函数模板的匹配原则 类模板 类模板的定义格式 类模板的实例化 c的模板大致可以分为&#xff1a; 函数模板类模板 首先在我们引入模板之前&#xff0c;先进行介绍泛型编程 泛…

期权黑天鹅怎么应对?近期很有可能发生的事情!

今天带你了解期权黑天鹅怎么应对&#xff1f;在当今世界&#xff0c;投资者们不断地寻找着各种策略来应对市场的波动和不确定性。其中&#xff0c;黑天鹅策略在近年来逐渐受到了广泛的关注&#xff0c;这种策略主要是利用极端事件&#xff0c;例如突发事件或自然灾害等难以预测…

【React笔记初学总结一】React新手的学习流程笔记总结,掰开了揉碎了,下载安装基础结构学习

REACT学习记录 一、React是什么&#xff1a;二、尝试安装下载&#xff1a;三、理解都有什么四、基础网页学习&#xff1a;1.几个比较重要的资源包例子2.第一个react示例&#xff1a;&#xff08;掰开了揉碎了&#xff0c;咱们先看懂它最简单的结构&#xff09;3.第二个react示例…

C++链接FTP服务器并下载数据(在qt中编写)

.pro文件 #------------------------------------------------- # # Project created by QtCreator 2024-07-16T13:19:03 # #-------------------------------------------------QT core gui networkgreaterThan(QT_MAJOR_VERSION, 4): QT widgetsTARGET untitled TE…

Qt实现IP地址输入框-自定义控件

在 许多应用程序中&#xff0c;我们经常需要使用IP地址。为了方便用户输入和处理&#xff0c;一个好的解决方案是使用自定义控件。本示例代码使用Qt编写一个名为“IPAddress”的自定义控件来实现IP地址的输入功能。通过使用此控件&#xff0c;用户可以方便地输入和处理IP地址。…

吴恩达机器学习笔记 三十八 二进制标签 均值归一化

标签 0 和 1 可以有很多种意义。从回归到二分分类&#xff1a;之前定义 ,而对于二进制标签&#xff0c;通过给出y^(i,j)为 1 的概率&#xff0c;其中 损失函数 均值归一化 计算每个电影的平均得分&#xff0c;例如第一部电影的平均分为2.5&#xff0c;第五部电影的平均分为1.2…