C之(15)cppcheck使用介绍_cppcheck使用详解
C之(15)cppcheck使用介绍
Author: Once Day Date: 2025年3月23日
一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦…
漫漫长路,有人对你微笑过嘛…
全系列文章可查看专栏: Linux实践记录_Once_day的博客-CSDN博客
参考文章:
- CppCheck静态代码检查工具教程【Windows和Linux端】-CSDN博客
- cppcheck的安装及基本使用_cppcheck这个操作只对当前安装的产品有效-CSDN博客
- Cppcheck - A tool for static C/C++ code analysis
文章目录
- C之(15)cppcheck使用介绍
-
-
-
- 1. cppcheck介绍
-
- 1.1 概述
- 1.2 检查结果
- 1.3 检查规则和过滤
- 2. 基本使用方法
- 3. 参数介绍
- 4. gitlab-ci集成
-
-
1. cppcheck介绍
1.1 概述
Cppcheck是一款静态代码分析工具,专门用于检查C/C++代码中潜在的错误和漏洞。它由瑞典程序员Daniel Marjamäki在2007年开发,旨在帮助开发者提高代码质量,减少bug。
Cppcheck的诞生源于Daniel在工作中遇到的一些棘手的编程问题。他发现,许多C/C++项目中存在许多常见的编码错误,如内存泄漏、未初始化变量、数组越界等,这些问题不易被发现,但却可能导致程序崩溃或产生安全隐患。为了解决这一痛点,Daniel利用业余时间开发了Cppcheck。
最初,Cppcheck只是一个简单的命令行工具,功能较为单一。但随着时间推移,在全球开源社区的共同努力下,Cppcheck不断完善,功能日益强大。目前,它已经成为了C/C++开发者必不可少的代码检查工具之一,被广泛应用于各种项目中,从小型单机程序到大型服务器软件,涵盖领域十分广泛。
Cppcheck的核心价值在于提升代码质量,减少潜在错误。它通过静态分析代码,能够精确地定位出各种问题,如unused functions、unexpectedsign、uninitialized variables等,并给出改进建议。同时,Cppcheck也提供了丰富的自定义规则,用户可以根据自己的需求进行个性化设置。
使用Cppcheck非常简单,通常只需一行命令即可。例如,要检查当前目录下的所有.cpp文件,只需执行:
cppcheck --enable=all .
Cppcheck就会自动分析每个文件,输出检查结果,并指出问题所在的行号和具体原因。用户可以根据这些信息快速定位并修复代码缺陷,大大提高开发效率。
除了命令行,Cppcheck还支持多种集成方式,可以与Visual Studio、Eclipse等流行IDE无缝对接,实现图形化操作。同时,Cppcheck也提供了Python绑定,方便进行二次开发和功能扩展。
1.2 检查结果
Cppcheck的检查结果主要分为以下几类:
(1)Error(错误):这是最严重的问题,意味着代码中存在明显的缺陷或漏洞,可能导致程序崩溃、数据损坏等危险后果。
- 内存泄漏:动态分配的内存没有被正确释放,长期积累可能耗尽系统资源。
- 悬空指针:指针指向了已经释放的内存区域,再次使用可能引发无法预料的错误。
- 除零错误:将一个数除以0会导致程序异常退出。
- 数组越界:访问了数组边界之外的内存,可能覆盖其他关键数据。
(2)Warning(警告):Warning通常指出了代码中的一些不规范或可疑的写法,虽然不会直接导致错误,但可能隐藏着潜在的bug。开发者应该仔细检查这些警告,采取防御性编程策略,以提高代码的健壮性。
- 未初始化变量:变量在使用前没有赋予初值,其内容是不可预知的。
- 死代码:一些永远不会被执行到的代码片段,通常暗示存在BUG。
- 忽略返回值:忽略了某些函数的返回值,可能错过了重要的错误信息。
(3)Style(编码风格):Style指出了代码的一些格式问题,虽然不影响程序的功能,但影响可读性、可维护性。
- 未使用的函数:定义了一些函数,但在代码中并未被调用,建议删除。
- 多余的代码:一些无用的变量定义、赋值、条件判断等,应该剔除。
- 缩进不规范:没有遵循统一的缩进标准,使代码显得混乱。
(4)Portability(移植性):Portability提示了代码在跨平台、跨编译器时可能遇到的兼容性问题。
- 大小端问题:不同CPU架构下,多字节数据的存储顺序可能相反。
- 数据类型长度:不同平台下,int、long等类型的字节长度可能不一致。
- 特定编译器的语法:使用了某些编译器特有的语法,在其他编译器下可能无法通过编译。
(5)Performance(性能):Performance给出了一些优化代码性能的建议,帮助开发者写出更高效的程序。
- 循环展开:建议将一些小循环展开,以减少迭代次数。
- 避免不必要的临时对象:在循环内部创建大量临时对象,建议放在循环外处理。
(6)Information(信息):Information是一些有趣的提示信息,不太重要,可以忽略。
- 幻数:代码中用到了一些未命名的神秘数字,难以猜测其含义。
- 文档格式:doxygen等文档注释的格式不标准。
1.3 检查规则和过滤
Cppcheck提供了丰富的检查规则,可以从多个维度审视代码质量。
尽管Cppcheck可以发现很多问题,但有时候我们可能希望忽略某些特定类型的警告,这时就可以使用--suppress
选项进行过滤。
例如,使用下面的命令可以屏蔽所有的shadowVariable
警告:
cppcheck --suppress=shadowVariable test.cpp
如果要屏蔽多个警告,可以用逗号分隔:
cppcheck --suppress=shadowVariable,unusedFunction test.cpp
除了按警告类型过滤,Cppcheck还支持更精细的过滤条件,如按文件、行号等。
2. 基本使用方法
在Ubuntu系统上安装和使用Cppcheck非常方便,下面我们就一步步来看看具体的操作过程。
打开终端,执行以下命令安装Cppcheck:
sudo apt-get updatesudo apt-get install cppcheck
等待安装完成后,可以通过–version选项检查安装是否成功:
cppcheck --version
如果显示了Cppcheck的版本号,说明安装成功。
要检查一个C/C++源文件,只需在终端中执行:
cppcheck test.cpp
Cppcheck就会自动分析test.cpp中的代码,并输出检查结果。
如果要检查多个文件,可以直接将它们作为参数传给Cppcheck:
cppcheck test1.cpp test2.cpp test3.cpp
要检查一个目录下的所有源文件,可以使用通配符:
cppcheck src/*.cpp
上述命令会检查src目录下的所有.cpp文件。
默认情况下,Cppcheck只会执行一些基本的检查。如果要启用所有检查,可以加上--enable=all
选项:
cppcheck --enable=all test.cpp
这会启用所有的警告和建议,可以更全面地发现潜在问题。
下面我们用一个具体的例子来演示Cppcheck的使用。假设我们有以下一个简单的C++程序(test.cpp):
#include using namespace std;int main() { int* p = new int[10]; p[10] = 1; // 数组越界 delete[] p; int a; cout << a << endl; // 使用未初始化的变量 return 0;}
这个程序有两个明显的错误:数组越界和使用未初始化的变量。下面我们用Cppcheck来检查它:
cppcheck --enable=all test.cpp
Cppcheck会输出类似以下的结果:
Checking test.cpp ...test.cpp:1:0: information: Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results. [missingIncludeSystem]#include ^test.cpp:6:6: error: Array \'p[10]\' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds] p[10] = 1; // 数组越界 ^test.cpp:10:13: error: Uninitialized variable: a [uninitvar] cout << a << endl; // 使用未初始化的变量 ^test.cpp:9:9: style: Variable \'a\' is not assigned a value. [unassignedVariable] int a; ^nofile:0:0: information: Active checkers: 161/592 (use --checkers-report= to see details) [checkersReport]
可以看到,Cppcheck准确地发现了这两个错误,并指出了对应的代码行。我们可以据此快速定位和修复这些问题。
3. 参数介绍
Cppcheck的基本语法格式为:
cppcheck [OPTIONS] [files or paths]
如果输入参数是目录,那么目录下面的*.cpp
, *.cxx
, *.cc
, *.c++
, *.c
, *.ipp
,*.ixx
, *.tpp
, *.txx
等文件会被依次递归的检查。
--cppcheck-build-dir=
--check-level=
--checkers-report=
--clang=
--config-exclude=
--config-excludes-file=
--disable=
--file-filter=
的文件,可多次使用--file-list=
--include=
--includes-file=
-l
--language=
--output-file=
--plist-output=
--project-configuration=
--rule-file=
--showtime=
--suppressions-list=
--suppress-xml=
--template-location=\'\'
Cppcheck 还有一些其他参数未在表格中列出,具体可参考完整的命令行帮助信息。
4. gitlab-ci集成
下面展示一种将Cppcheck集成到gitlab ci流水线的方法,GitHub和Gitee都可以以此作为参考:
首先需要一个运行Cppcheck的脚本run_cppcheck.sh
,在该脚本里指定Cppcheck运行参数和处理结果:
# 当前目录路径export SOURCE_DIR=${SOURCE_DIR:-$(pwd)}# 定义参数# 除了 missingInclude 其他都是默认开启的CPP_ARGS=\"--enable=style,performance,portability,unusedFunction,information\"CPP_ARGS=\"$CPP_ARGS --disable=missingInclude\"# 忽略不确定的检查CPP_ARGS=\"$CPP_ARGS --inconclusive\"# 强制检查所有文件CPP_ARGS=\"$CPP_ARGS --force\"# 忽略内联的警告CPP_ARGS=\"$CPP_ARGS --inline-suppr\"CPP_ARGS=\"$CPP_ARGS --library=posix\"# 指定C和C++的标准CPP_ARGS=\"$CPP_ARGS --std=c++11 --std=c11 --fsigned-char\"# 发现错误时 exit-code = 1CPP_ARGS=\"$CPP_ARGS --error-exitcode=1\"# set -x# 对代码进行静态检查cppcheck $CPP_ARGS $SOURCE_DIR/anmk/if [ $? -ne 0 ]; then echo \"Cppcheck failed\" exit 1fiecho \"Cppcheck success\"exit 0
首先,脚本设置了 SOURCE_DIR 环境变量,表示源代码的根目录路径,默认为当前目录。
接下来,通过 CPP_ARGS 变量定义了传递给 Cppcheck 的各种参数:
--enable
: 启用额外的检查,如编码风格、性能、可移植性、未使用函数、信息提示等。--disable
: 禁用 missingInclude 检查。--inconclusive
: 允许 Cppcheck 报告不确定的结果。--force
: 强制检查所有文件和编译配置。--inline-suppr
: 支持使用行内抑制注释。--library
: 使用 POSIX 库进行分析。--std
: 指定 C 和 C++ 的语言标准。--error-exitcode
: 发现错误时返回非零的退出码。
然后,脚本运行 Cppcheck 命令,将 SOURCE_DIR/anmk/ 目录下的代码作为分析对象,应用之前定义的所有参数。
通过检查 Cppcheck 的返回值,如果不为0,说明存在静态分析问题,脚本输出错误信息并以非零状态码退出;反之则代表检查通过,脚本输出成功信息并正常退出。
.gitlab-ci.yml
配置如下:
# 本地构建阶段 - 代码静态检查, 存在静态检查问题则失败develop-static-check: stage: local-build tags: - anmk-build needs: [] script: - echo \"Check ANMK Project - Develop Version - Static\" - ./run_cppcheck.sh - echo \"Check finished\"
定义了一个名为 develop-static-check
的job,用于对开发版本的代码进行静态检查。
该job在 local-build 阶段运行,使用 anmk-build 的标签来选择合适的runner。
needs: []
表示该job不依赖于其他任务,可以独立运行。
script 部分定义了该job的运行脚本:
- 输出提示信息,表示开始对开发版本的ANMK项目代码进行静态检查。
- 调用 run_cppcheck.sh 脚本执行实际的静态分析过程。
- 输出提示信息,表示静态检查已完成。
通过这样的集成,每次提交或合并请求时,GitLab 都会自动触发 develop-static-check job,对代码进行 Cppcheck 静态分析。如果发现问题,流水线会失败并及时反馈,促使开发者尽快修复。
这种自动化的静态代码检查可以帮助提早发现代码缺陷,提高代码质量,减少后续的调试和维护成本。
Once Day
也信美人终作土,不堪幽梦太匆匆......
如果这篇文章为您带来了帮助或启发,不妨点个赞👍和关注,再加上一个小小的收藏⭐!
(。◕‿◕。)感谢您的阅读与支持~~~