Cppcheck 用法(上篇)

简述

Cppcheck 是一种 C/C++ 代码缺陷静态检查工具。不同于 C/C++ 编译器及很多其它分析工具,它不检查代码中的语法错误。Cppcheck 只检查编译器检查不出来的 bug 类型,其目的是检查代码中真正的错误(即:零误报)。

  • 简述
  • 介绍
  • 开始使用
    • 第一个测试程序
    • 检查文件夹中的所有文件
    • 手动检查文件或使用项目文件
    • 检查时排除某个文件或文件夹
    • 严重性
    • 启用消息
    • 不确定消息
    • 保存结果到文件中
    • 多线程检查
    • 平台
  • 项目
    • CMake
    • Visual Studio
  • 预处理器设置
    • 定义
  • XML 输出
    • error 元素
    • location 元素
  • 格式化输出
  • 更多参考

介绍

支持的代码和平台:

  • 可以检查非标准代码,包括不同的编译器扩展、内联汇编代码等。
  • Cppcheck 应该被处理最新 C++ 标准的任何 C++ 编译器所编译。
  • Cppcheck 应该在任何有足够 CPU 和内存的平台上工作。

要知道 Cppcheck 有限制,Cppcheck 很少在报告错误方面出错,但有很多 bug,它不能检测。

通过仔细测试软件,你会发现软件中有更多的 bug,而不是使用 Cppcheck。但 Cppcheck 仍可以检测到在测试和评估软件时错过的一些 bug。

开始使用

第一个测试程序

这里有一段简单的代码:

int main()
{
    char a[10];
    a[10] = 0;
    return 0;
}

将代码保存进 file.c 文件中,执行:

cppcheck file.c

注意:执行此命令前,需要将 cppcheck.exe 所在路径添加至环境变量 PATH 中。

这时,将会从 cppcheck 中输出:

Checking file.c …
[file.c:4]: (error) Array ‘a[10]’ accessed at index 10, which is out of bounds.

检查文件夹中的所有文件

通常一个项目会有许多源文件,如果需要同时检查,Cppcheck 可以检查文件夹中的所有文件:

cppcheck path

如果 path 是一个文件夹,cppcheck 将递归检查这个文件夹中的所有源文件。

Checking path/file1.cpp…
1/2 files checked 50% done
Checking path/file2.cpp…
2/2 files checked 100% done

手动检查文件或使用项目文件

使用 Cppcheck 可以手动检查文件,通过指定文件/文件夹来检查和设置,或者可以使用一个工程文件(cmake/visual studio)。

使用项目文件更快,因为它只需要非常少的配置。

手动检查文件可以更好的控制分析。

不一定哪种方法会有最好的结果,建议尝试一下,可能会得到不同的结果,发现大多数 bug 需要使用这两种方法。

检查时排除某个文件或文件夹

排除一个文件或文件夹有两个选项,第一个选项是只提供你想检查的路径和文件:

cppcheck src/a src/b

所有位于 src/a 和 src/b 下的文件都会被检查。

方式二:使用 -i 选项

这时,将会忽略指定的文件/文件夹,使用下面命令在 src/c 将不会被检查:

cppcheck -isrc/c src

严重性

可能的严重性消息有:

  • 错误
    当发现 bug 时使用
  • 警告
    关于防御性编程,以防止 bug 的建议
  • 风格警告
    风格有关问题的代码清理(未使用的函数、冗余代码、常量性等等)
  • 可移植性警告
    可移植性警告。64 位的可移植性,代码可能在不同的编译器中运行结果不同。
  • 性能警告
    建议使代码更快。这些建议只是基于常识,即使修复这些消息,也不确定会得到任何可测量的性能提升。
  • 信息消息
    配置问题,建议在配置期间仅启用这些。

启用消息

默认情况下,只显示错误消息,可以通过 --enable 命令启用更多检查。

启用警告消息:

cppcheck --enable=warning file.c

启用性能消息:

cppcheck --enable=performance file.c

启用信息消息:

cppcheck --enable=information file.c

由于历史原因 --enable=style 可以启用警告、性能、可移植性和样式信息。当使用旧 XML 格式时,这些都由 style 表示:

cppcheck --enable=style file.c

启用警告和性能消息:

cppcheck --enable=warning,performance file.c

启用 unusedFunction 检查。这不能通过 --enable=style 启用,因为不会在库中正常工作。

cppcheck --enable=unusedFunction file.c

启用所有消息:

cppcheck --enable=all

不确定消息

默认情况下,如果确定,Cppcheck 只显示错误消息。如果使用 --inconclusive,当分析不确定时,也会写错误消息。

cppcheck --inconclusive path

这当然会导致错误的警告,即使在没有 bug 的情况下,也可能会报 bug。如果可以接受错误的警告,可以使用此命令。

保存结果到文件中

很多时候,会希望将结果保存在一个文件中,可以使用 shell 的管道重定向错误输出到一个文件:

cppcheck file.c 2> err.txt

多线程检查

选项 -j 用于指定需要使用的线程数,例如,使用 4 个线程检查文件夹中的文件:

cppcheck -j 4 path

注意:这将禁用 unusedFunction 检查。

平台

应该使用一个与你的目标匹配的平台配置。

默认情况下,如果代码在本地编译和执行,Cppcheck 会使用本地平台配置。

Cppcheck 具有用于 Unix 和 Windows 目标的内置配置,可以轻松地使用这些 --platform 命令行标志。

还可以在 XML 文件中创建自己的自定义平台配置。这里有一个例子:

<?xml version="1"?>
<platform>
  <char_bit>8</char_bit>
  <default-sign>signed</default-sign>
  <sizeof>
    <short>2</short>
    <int>4</int>
    <long>4</long>
    <long-long>8</long-long>
    <float>4</float>
    <double>8</double>
    <long-double>12</long-double>
    <pointer>4</pointer>
    <size_t>4</size_t>
    <wchar_t>2</wchar_t>
  </sizeof>
</platform>

项目

当使用 CMake 或 Visual Studio 时,可以使用 --project 来分析项目。

它会给你快速和简单的结果,不需要做太多的配置。但很难说这是否将会给你最好的结果,建议试一试它,并尝试不使用 --project 分析源代码,看哪个选项更适合。

CMake

Cppcheck 可以理解编译数据库,可以用 CMake 生成这些。

例如:

$ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

文件 compile_commands.json 在当前文件夹中创建。

现在像这样运行 Cppcheck:

$ cppcheck --project=compile_commands.json

Visual Studio

可以对单个项目文件(*.vcxproj)或整个解决方案(*.sln)运行 Cppcheck。

在整个解决方案上运行 cppcheck:

$ cppcheck --project=foobar.sln

在单个项目文件上运行 cppcheck:

$ cppcheck --project=foobar.vcxproj

注意:还有一个 Visual Studio 插件,允许在 Visual Studio 中运行 cppcheck。

预处理器设置

如果使用 --project,那么 Cppcheck 将使用项目文件中的预处理器设置。

否则,可能需要配置包含路径,定义等。

定义

这有一个文件,有两个配置(定义和没定义 A):

#ifdef A
    x = y;
#else
    x = z;
#endif

默认情况下,Cppcheck 将检查所有预处理器配置(除了那些具有 #error 的配置),所以上述代码将被分析在当 A 定义和不定义的情况下。

可以使用 -D 更改。当使用 -D 时,cppcheck 将默认只检查给定的配置,不会检查其它,这就是编译器的工作原理。但是可以使用 --force--max-configs 来覆盖配置数量。

检查所有配置:

cppcheck file.c

只检查配置 A:

cppcheck -DA file.c

当定义宏 A 时,检查所有配置:

cppcheck -DA --force file.c

另一个有用的标志可能是 -U,它未定义符号。 用法示例:

cppcheck -UX file.c

这意味着 X 没有定义,Cppcheck 不会检查当定义 X 时会发生什么。

XML 输出

Cppcheck 可以生成 XML 格式的输出。有一个旧的 XML 格式(version 1)和一个新的 XML 格式(version 2)。如果可以,请使用新版本。

旧版本保持向后兼容性。它不会改变,但有一天可能会被删除。使用 --xml 支持这种格式。

新版本修复一些旧格式的问题。新格式可能会在 cppcheck 的未来版本中更新,并带有新的属性和元素。用于检查文件并以新的 XML 格式输出错误的示例命令:

cppcheck --xml-version=2 file.cpp

这是一个 version 2 示例:

<?xml version="1.0" encoding="UTF-8"?>
<results version="2">
  <cppcheck version="1.66">
  <errors>
    <error id="someError" severity="error" msg="short error text"
           verbose="long error text" inconclusive="true" cwe="312">
      <location file0="file.c" file="file.h" line="1"/>
    </error>
  </errors>
</results>

<error> 元素

每个错误都在 <error> 元素中,属性:

  • id
    错误的 id,这些都是有效的符号名称。
  • severity
    error、warning、style、performance、portability、information 中的任何一个。
  • msg
    短格式的错误消息
  • verbose
    长格式的错误消息
  • inconclusive
    此属性仅在消息不确定时使用
  • cwe
    消息的 CWE ID,此属性仅在消息的 CWE ID 已知时使用。

<location> 元素

<location> 元素列出所有错误相关位置,首先列出主要位置。

属性:

  • file
    文件名,相对路径和绝对路径都是可能的。
  • file0
    源文件的名称(可选)
  • line
    一个数字
  • msg
    此属性尚不存在,但将来可以为每个位置添加一条短消息。

格式化输出

如果想重新格式化输出,使它看起来不同,可以使用模板。

要获得 Visual Studio 兼容的输出,可以使用 --template=vs

cppcheck --template=vs gui/test.cpp

输出将如下所示:

Checking gui/test.cpp…
gui/test.cpp(31): error: Memory leak: b
gui/test.cpp(16): error: Mismatching allocation and deallocation: k

要获得 gcc 兼容的输出,可以使用 --template=gcc

cppcheck --template=gcc gui/test.cpp

输出将如下所示:

Checking gui/test.cpp…
gui/test.cpp:31: error: Memory leak: b
gui/test.cpp:16: error: Mismatching allocation and deallocation: k

可以编写自己的模式(例如,逗号分隔格式):

cppcheck --template="{file},{line},{severity},{id},{message}" gui/test.cpp

输出将如下所示:

Checking gui/test.cpp…
gui/test.cpp,31,error,memleak,Memory leak: b
gui/test.cpp,16,error,mismatchAllocDealloc,Mismatching allocation and deallocation: k

支持以下格式说明符:

  • callstack
    调用栈 - 如果可用
  • file
    文件名
  • id
    消息 id
  • line
    行号
  • message
    详细的消息文本
  • severity
    一个消息的类型/等级

支持转义序列: \b(退格)、\n(换行)、\r(换页)、\t(水平制表符)

更多参考

时间: 2024-09-17 22:07:08

Cppcheck 用法(上篇)的相关文章

Java 中的 XML:Java 文档模型的用法

xml 在本系列的第一篇文章中,我研究了一些用 Java 编写的主要的 XML 文档模型的性能.但是,在开始选择这种类型的技术时,性能只是问题的一部分.使用方便至少是同样重要的,并且它已是一个主要理由,来支持使用 Java 特定的模型,而不是与语言无关的 DOM . 为切实了解哪个模型真正的作用,您需要知道它们在可用性程度上是如何排名的.本文中,我将尝试进行这个工作,从样本代码开始,来演示如何在每个模型中编码公共类型的操作.并对结果进行总结来结束本文,而且提出了促使一种表示比另一种更容易使用的一

Java中的XML: Java文档模型的用法

在本系列的第一篇文章中,我研究了一些用 Java 编写的主要的 XML 文档模型的性能.但是,在开始选择这种类型的技术时,性能只是问题的一部分.使用方便至少是同样重要的,并且它已是一个主要理由,来支持使用 Java 特定的模型,而不是与语言无关的 DOM . 为切实了解哪个模型真正的作用,您需要知道它们在可用性程度上是如何排名的.本文中,我将尝试进行这个工作,从样本代码开始,来演示如何在每个模型中编码公共类型的操作.并对结果进行总结来结束本文,而且提出了促使一种表示比另一种更容易使用的一些其它因

jquery中load方法的用法及注意事项说明

 本篇文章主要是对jquery中load方法的用法及注意事项进行了详细介绍,需要的朋友可以过来参考下,希望对大家有所帮助 调用load方法的完整格式是:load( url, [data], [callback] ),其中  url:是指要导入文件的地址.  data:可选参数:因为Load不仅仅可以导入静态的html文件,还可以导入动态脚本,例如PHP文件,所以要导入的是动态文件时,我们可以把要传递的参数放在这里.  callback:可选参数:是指调用load方法并得到服务器响应后,再执行的另

深入理解JavaScript系列(49):Function模式(上篇)_基础知识

介绍 本篇主要是介绍Function方面使用的一些技巧(上篇),利用Function特性可以编写出很多非常有意思的代码,本篇主要包括:回调模式.配置对象.返回函数.分布程序.柯里化(Currying). 回调函数 在JavaScript中,当一个函数A作为另外一个函数B的其中一个参数时,则函数A称为回调函数,即A可以在函数B的周期内执行(开始.中间.结束时均可). 举例来说,有一个函数用于生成node 复制代码 代码如下: var complexComputation = function ()

Android中Intent习惯用法_Android

Android中的Intent是一个非常重要的类,如果对Intent不是特别了解,可以参见<详解Android中Intent的使用方法>.如果对Intent Filter不是特别了解,可以参见<详解Android中Intent对象与Intent Filter过滤匹配过程>. 本文着重讲一下Android中一些常见的Intent的习惯用法,比如如何通过Intent发送短信.发送邮件.启动摄像机拍照录视频.设置闹铃.打开WIFI设置界面等等. 限于篇幅,本文分为上下两篇,这是上篇. 发

Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/43536355 大家好,在上一篇文章当中,我们学习了Android属性动画的基本用法,当然也是最常用的一些用法,这些用法足以覆盖我们平时大多情况下的动画需求了.但是,正如上篇文章当中所说到的,属性动画对补间动画进行了很大幅度的改进,之前补间动画可以做到的属性动画也能做到,补间动画做不到的现在属性动画也可以做到了.因此,今天我们就来学习一下属性动画的高级用法,看看如何实现一些补间动画

Python协程:概念及其用法

真正有知识的人的成长过程,就像麦穗的成长过程:麦穗空的时候,麦子长得很快,麦穗骄傲地高高昂起,但是,麦穗成熟饱满时,它们开始谦虚,垂下麦芒. --蒙田<蒙田随笔全集> 上篇<Python 多线程鸡年不鸡肋>论述了关于python多线程是否是鸡肋的问题,得到了一些网友的认可,当然也有一些不同意见,表示协程比多线程不知强多少,在协程面前多线程算是鸡肋.好吧,对此我也表示赞同,然而上篇我论述的观点不在于多线程与协程的比较,而是在于IO密集型程序中,多线程尚有用武之地. 对于协程,我表示其

Android属性动画完全解析(下) Interpolator和ViewPropertyAnimator的用法

大家好,欢迎继续回到Android属性动画完全解析.在上一篇文章当中我们学习了属性动画的一些进阶技巧,包括ValueAnimator和ObjectAnimator的高级用法,那么除了这些之外,当然还有一些其它的高级技巧在等着我们学习,因此本篇文章就对整个属性动画完全解析系列收个尾,来学习一下剩下的非常重要的高级技巧. 另外,本篇文章中使用的代码是建立在上篇文章基础之上的,如果你还没有阅读过前面的文章,建议先去参考阅读一下 Android属性动画完全解析(中),ValueAnimator和Obje

细说 ASP.NET Cache 及其高级用法

原文:细说 ASP.NET Cache 及其高级用法 许多做过程序性能优化的人,或者关注过程程序性能的人,应该都使用过各类缓存技术. 而我今天所说的Cache是专指ASP.NET的Cache,我们可以使用HttpRuntime.Cache访问到的那个Cache,而不是其它的缓存技术. 以前我在[我心目中的Asp.net核心对象] 这篇博客中简单地提过它,今天我打算为它写篇专题博客,专门来谈谈它,因为它实在是太重要了.在这篇博客中, 我不仅要介绍它的一些常见用法,还将介绍它的一些高级用法. 在上篇