首页 > 其他分享 >#盲盒+码# Clang Static Analyzer (3) Cppcheck

#盲盒+码# Clang Static Analyzer (3) Cppcheck

时间:2022-12-12 14:32:11浏览次数:56  
标签:10 style enable -- Analyzer Static cppcheck Cppcheck

【本文正在参加「盲盒」+码有奖征文活动】https://ost.51cto.com/posts/19288

Clang Static Analyzer (3) Cppcheck

前文介绍CodeChecker时,使用到了Cppcheck,我们来看看这个工具是什么,如何使用。

1、Cppcheck介绍

Cppcheck 是 C/C++ 代码的静态分析工具。它提供独特的代码分析技术来检测缺陷,不检查代码中的语法错误,只检查编译器检查不出来的缺陷,并专注于检测未定义行为错误和危险的编码结构。其目标是减少误报、零误报,检查代码中真正的错误。Cppcheck旨在能够分析C / C++代码,即使它具有非标准语法(在嵌入式项目中很常见)。

Cppcheck既有开源版本,也有具有扩展的功能和支持的Cppcheck Premium版本,。可以访问 www.cppchecksolutions.com 以获取商业版本的更多信息和购买选项。

1.1、Cppcheck功能特性

  • 独特的代码分析,可检测代码中的各种错误。

  • 命令行界面和图形用户界面都可用。

  • Cppcheck非常注重检测未定义的行为。

1.2、Cppcheck特有的分析技术

使用多个静态分析工具可能是一个好主意,每个工具都有独特的功能特性。这在研究中已经证实。那么Cppcheck的独特之处在哪里?

Cppcheck使用不健全的流程敏感分析,其他几种分析器使用基于抽象解释的路径敏感分析,这也很好,但既有优点也有缺点。从理论上讲,根据定义,路径敏感分析比流量敏感分析更好。但实际上,这意味着Cppcheck将检测其他工具无法检测到的错误。在Cppcheck中,数据流分析不仅是“前向”的,而且是“双向的”。大多数分析器会诊断这一点,可以确定数组索引为 1000 时会出现溢出。

void foo(int x)
{
    int buf[10];
    if (x == 1000)
        buf[x] = 0; // <- ERROR
}

Cppcheck还将诊断此问题,当x等于1000时,赋值时也会出现数组越界。

void foo(int x)
{
    int buf[10];
    buf[x] = 0; // <- ERROR
    if (x == 1000) {}
}

1.3、未定义行为Undefined behaviour

  • Dead pointers 死指针
  • Division by zero 除以零
  • Integer overflows整数溢出
  • Invalid bit shift operands无效的位移操作数
  • Invalid conversions无效转化
  • Invalid usage of STLSTL 的用法无效
  • Memory management内存管理
  • Null pointer dereferences空指针解引用
  • Out of bounds checking越界检查
  • Uninitialized variables未初始化的变量
  • Writing const data写入常量数据

2、Cppcheck安装

Cppcheck也可以从各种包管理器安装;但是,您可能会得到一个过时的版本。为了获取更新版本,可以访问https://github.com/danmar/cppcheck进行源码安装。

  • Debian:
sudo apt-get install cppcheck
  • Fedora:
sudo yum install cppcheck
  • macOS:
brew install cppcheck

3、使用入门

第一个测试程序,这里有一段简单的代码,我们命名为file1.c。

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

执行cppcheck file1.c,输出如下:

zhushangyuan@DESKTOP-RPE9R4O:~/CSA$ cppcheck file1.c
Checking file1.c ...
[file1.c:4]: (error) Array 'a[10]' accessed at index 10, which is out of bounds.

我们再试试上面说的例子,保存到file2.c。

void foo(int x)
{
  int buf[10];
  buf[x] = 0; // <- ERROR 1
  if (x == 1000) {
    buf[x] = 0; // <- ERROR 2
  }
}

执行cppcheck --enable=all file2.c,输出如下。可以看得出有2个warning和3个style问题。

zhushangyuan@DESKTOP-RPE9R4O:~/CSA$ cppcheck --enable=all file2.c
Checking file2.c ...
file2.c:4:6: warning: Either the condition 'x==1000' is redundant or the array 'buf[10]' is accessed at index 1000, which is out of bounds. [arrayIndexOutOfBoundsCond]
  buf[x] = 0; // <- ERROR 1
     ^
file2.c:5:9: note: Assuming that condition 'x==1000' is not redundant
  if (x == 1000) {
        ^
file2.c:4:6: note: Array index out of bounds
  buf[x] = 0; // <- ERROR 1
     ^
file2.c:6:8: warning: Either the condition 'x==1000' is redundant or the array 'buf[10]' is accessed at index 1000, which is out of bounds. [arrayIndexOutOfBoundsCond]
    buf[x] = 0; // <- ERROR 2
       ^
file2.c:5:9: note: Assuming that condition 'x==1000' is not redundant
  if (x == 1000) {
        ^
file2.c:6:8: note: Array index out of bounds
    buf[x] = 0; // <- ERROR 2
       ^
file2.c:4:10: style: Variable 'buf[x]' is assigned a value that is never used. [unreadVariable]
  buf[x] = 0; // <- ERROR 1
         ^
file2.c:6:12: style: Variable 'buf[x]' is assigned a value that is never used. [unreadVariable]
    buf[x] = 0; // <- ERROR 2
           ^
file2.c:1:0: style: The function 'foo' is never used. [unusedFunction]

^

3.1 检查文件夹

Cppcheck支持检查文件夹中的所有文件。通常一个项目会有许多源文件,如果需要同时检查,Cppcheck 可以检查文件夹中的所有文件.如果 path 是一个文件夹,cppcheck 将递归检查这个文件夹中的所有源文件。

cppcheck path

示例输出如下:

zhushangyuan@DESKTOP-RPE9R4O:~/CSA$ cppcheck .
Checking file1.c ...
file1.c:4:4: error: Array 'a[10]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]
  a[10] = 0;
   ^
1/4 files checked 12% done
Checking file2.c ...
2/4 files checked 38% done
Checking hello.c ...
hello.c:2:13: error: Division by zero. [zerodiv]
  int x = 7 / 0; // bug here
            ^
3/4 files checked 50% done
Checking simple.c ...
simple.c:16:11: error: Division by zero. [zerodiv]
  return 5/(x-x); // warn
          ^
simple.c:12:5: error: Uninitialized variable: s [uninitvar]
  f(s); // warn
    ^
simple.c:12:5: error: Uninitialized struct member: s.x [uninitStructMember]
  f(s); // warn
    ^
4/4 files checked 100% done

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

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

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

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

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

4、严重级别Severities

输出信息中的严重级别支持如下几种:

  • error 错误 when code is executed there is either undefined behavior or other error, such as a memory leak or resource leak。发现未定义行为或其他错误,例如内存泄露、资源泄露
  • warning告警 when code is executed there might be undefined behavior可能有未定义行为
  • style样式风格 stylistic issues, such as unused functions, redundant code, constness, operator precedence, possible mistakes.样式问题,例如未使用行数,冗余代码,常量性,操作符优先级,可能的错误等
  • performance性能 run time performance suggestions based on common knowledge, though it is not certain any measurable speed difference will be achieved by fixing these messages.这些建议只是基于常识,即使修复这些消息,也不确定会得到任何可测量的性能提升。
  • portability可移植性 portability warnings. Implementation defined behavior. 64-bit portability. Some undefined behavior that probably works “as you want”, etc.可移植性警告。64 位的可移植性,代码可能在不同的编译器中运行结果不同。
  • information信息 configuration problems, which does not relate to the syntactical correctness, but the used Cppcheck configuration could be improved.配置问题,建议在配置期间仅启用这些

4.1 启用消息

默认情况下,只显示错误消息,可以通过 --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

5、常见错误修改

  • 隐式构造问题

示例: (style) Class ‘Slice’ has a constructor with 1 argument that is not explicit.

解决方法:在Slice构造函数前加上explicit,使其必须显示构造,当然这种有时并非必须显示构造

  • 变量未初始化问题

示例:(warning) Member variable ‘TableFileCreationInfo::file_size’ is not initialized in the constructor.

解决方法:在构造函数中加入变量初始值

  • 变量/函数未使用问题

示例:(style) Unused variable: output

示例:(style) The function ‘rocksmt_wal_iter_status’ is never used.

解决方法:考虑后期是否还需要,不需要的及时删除,需要的保留

  • raw loop问题

示例:(style) Consider using std::fill algorithm instead of a raw loop. [useStlAlgorithm]

示例:(style) Consider using std::transform algorithm instead of a raw loop. [useStlAlgorithm]

解决办法:将循环便利替换为STL标准库算法函数

  • 引用传递问题

示例:(performance) Function parameter ‘f’ should be passed by reference.

解决办法:在声明function时,能用引用传递的尽量使用引用传递,尽量避免值传递

  • const参数问题

示例:(performance) Function parameter ‘s’ should be passed by const reference. [passedByValue]

解决办法:形参s前加上const,在函数中未被修改的变量,尽量声明为const

6、参考站点

本文作者:zhushangyuan_

想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com/#bkwz​

标签:10,style,enable,--,Analyzer,Static,cppcheck,Cppcheck
From: https://blog.51cto.com/harmonyos/5929581

相关文章

  • 【JAVA笔记】JAVA-抽象类-final-static关键字-接口用法05
    一. 抽象类1、抽象类概述案例:Animal类(父类(抽象类))packagePackage1;//父类:动物类(抽象类)publicabstractclassAnimal{//抽象方法(特点:要求子类必须重写)......
  • MFC--StaticText静态文本框控件
    CStatic类提供了一个Windows静态控件的性能。一个静态控件用来显示一个文本字符串、框、矩形、图标、光标、位图或增强的图元文件。它可以被用来作为标签,框,或用来分隔其它的......
  • 【C内存模型】static 变量在内存中的位置
    C内存模型简单才是真理,所以我在参考了来自https://blog.csdn.net/second60/article/details/79946310的图后自己画了一个图栈:函数参数、函数内部创建的临时变量都存......
  • C++那些事-static
    static那些事关于作者微信公众号:当与不同类型一起使用时,Static关键字具有不同的含义。我们可以使用static关键字:静态变量:函数中的变量,类中的变量静态类的成员:类对......
  • #盲盒+码# Clang Static Analyzer (2) CodeChecker
    【本文正在参加「盲盒」+码有奖征文活动】https://ost.51cto.com/posts/19288ClangStaticAnalyzer(2)CodeChecker1、ClangStaticAnalyzer介绍Clang静态分析器CSA是......
  • #盲盒+码# Clang Static Analyzer (1) scan-build
    1、ClangStaticAnalyzer介绍Clang静态分析器CSA是一个源代码分析工具,可查找C、C++和Objective-C程序的bugs。目前可以从命令行中运行,或者如果您使用macOS,则可以在......
  • AFL(十七)qemu模式报错 util/memfd.c:40:12: error: static declaration of ‘memfd_cre
    qemu模式使用需要进入qemumode文件夹,然后运行那个sh脚本,但是会报错:util/memfd.c:40:12:error:staticdeclarationof‘memfd_create’followsnon-staticdeclarati......
  • static
    带static的方法,和不带static的方法,带静态修饰符的是普通方法,不带的是实例方法。实例方法不能直接引用,要先new对象,不然就会报错。不带static是对象级别的行为,带上stati......
  • static的三种用法
    ①static修饰局部变量局部变量的生命周期变长,通俗点说就是被static修饰的局部变量出了所限制的这个局部还能使用。②static修饰全局变量改变了变量的作用域-让静态的全......
  • C++学习笔记——static累加
    //#include<iostream>//usingnamespacestd;////classStu//{//public://staticintb;//静态成员无论赋值如何变化,一个静态成员只有一个空间//......