通用分析

PVS - Studio产品包含了一套通用静态分析规则,用于检测在C / C ++/ C+11应用程序中大范围内的各种缺陷。

通用的规则集帮助您发现逻辑错误,拼写错误,导致访问冲突的代码片段,STL库算法的不正确使用等。

当选择PVS – Studio的执行规则时,我们首先要从他们的相关性开始。我们自觉拒绝执行像MISRA这样的标准,因为那里的大多数建议描述没有什么帮助,开发人员使用现代工具,如Visual Studio和STL,MFC,Qt和Boost等的库。在PVS-Studio中,我们尝试实施更好的诊断,不仅考虑C / C ++语言的细节,还考虑更高层次的模式以及代码和库的相互作用。许多检查是独一无二的,目前还没有被我们所熟悉的分析仪实现过。

PVS - Studio中检测到的错误模式是千差万别的。因此,我们接下来只说明工具有可以检测的某些类型错误。如果您想了解分析仪检测到的其他类型的错误,请参考相关文档。下面给出的错误样本均取自真实的项目。

当“+1”写错地方时,发生的错误

if ((t=(char *)realloc(next->name, strlen(name+1))))

{

next->name=t;

strcpy(next->name, name);

}

分析仪在这里发现了程序员不小心犯下的错误。程序分配比实际需要少2个字节的内存。为了纠正错误,你应该把“+1”从括号中拿出来。这是正确的代码:"realloc(next->name, strlen(name) + 1)"。

矩阵清理不彻底

#define CONT_MAP_MAX 50

int _iContMap[CONT_MAP_MAX];

memset(_iContMap, -1, CONT_MAP_MAX);

这个错误是指缓冲区欠载/超载类的。当只是处理数组的部分,或者反过来,修改数组外的内存时,这样的错误就会发生。在此示例中,memset()函数只清除小部分的_iContMap阵列。这里的错误是缺少sizeof():

memset(_iContMap, -1, CONT_MAP_MAX * sizeof(_iContMap[0]));

缺少非关联指针

if (pSlash != NULL) {

pSlash++;

if (pSlash != '\0') {

...

分析仪通常可以帮助检测可疑的指针处理,例如,下面的示例。这里指针跟0比较。如果该指针不等于0,它就+1,再次和0比较。这是很奇怪的操作。他们当然包含一个错误,因为非关联指针操作丢失:“if(!* pSlash='\ 0'){”。

不正确的循环

int i, destlen = 0, l, k;

for (i=0; i<srclen; i++)

{

...

for (k=i; i<srclen; k++)

{

if (src[k]=='>')

break;

}

i = k;

}

分析仪在这段代码中发现了一个错字: “it”变量代替“K”,用在嵌套循环比较中。此代码是很容易造成内存访问到正在处理的数组以外。

写错变量名

class CSize : public SIZE

{

...

CSize(POINT pt) { cx = pt.x; cx = pt.y; }

这个错误在项目中被发现,程序员使用自己的类CSIZE。由于书写错误,结果一个相同的变量被分配不同的值。这引起分析仪的注意。第二次分配操作的正确代码是:“cy = pt.y;”。

Windows API使用不当

OPENFILENAME lofn;

...

lofn.lpstrFilter = L"Equalizer Preset (*.feq)\0*.feq";

在Windows API的结构中,字符串指针必须以两个零结尾。在此示例中,在OPENFILENAME结构的lpstrFilter成员是一个指针。此代码将在过滤文件中的对话领域中产生的垃圾。这是正确的代码:

lofn.lpstrFilter = L"Equalizer Preset (*.feq)\0*.feq\0";

我们手工在行末写“0”,因为编译器将会添加多一个0

标准算法处理不当

我们上面所讨论的所有示例是低级错误。现在让我们看看在PVS-Studio实施的检查,处理更高层次的概念,如代码块或算法。

void unregisterThread() {

Guard<TaskQueue> g(_taskQueue);

std::remove(_threads.begin(), _threads.end(), ThreadImpl::current());

}

std::remove函数不从存储器中删除的项目。它只是转移项目和返回到垃圾的迭代器的起点。假设我们有矢量<int>存储器,它包含项目1,2,3,1,2,3,1,2,3。假如我们执行代码"remove( v.begin(), v.end(), 2 )",容器将包含项目1,3,1,3,?,?,?,这里“?”是一些垃圾。此外,该函数将返回第一个垃圾项目的迭代器,所以如果我们要去除这些垃圾项目,我们必须编写以下代码:"v.erase(remove(v.begin(), v.end(), 2), v.end())".这是正确的代码:

auto trash = std::remove(_threads.begin(), _threads.end(),

ThreadImpl::current());

_threads.erase(trash, _threads.end());

使用复制-粘贴方法编写代码的错误

void KeyWordsStyleDialog::updateDlg()

{

...

Style & w1Style =

_pUserLang->_styleArray.getStyler(STYLE_WORD1_INDEX);

styleUpdate(w1Style, _pFgColour[0], _pBgColour[0],

IDC_KEYWORD1_FONT_COMBO, IDC_KEYWORD1_FONTSIZE_COMBO,

IDC_KEYWORD1_BOLD_CHECK, IDC_KEYWORD1_ITALIC_CHECK,

IDC_KEYWORD1_UNDERLINE_CHECK);

Style & w2Style =

_pUserLang->_styleArray.getStyler(STYLE_WORD2_INDEX);

styleUpdate(w2Style, _pFgColour[1], _pBgColour[1],

IDC_KEYWORD2_FONT_COMBO, IDC_KEYWORD2_FONTSIZE_COMBO,

IDC_KEYWORD2_BOLD_CHECK, IDC_KEYWORD2_ITALIC_CHECK,

IDC_KEYWORD2_UNDERLINE_CHECK);

Style & w3Style =

_pUserLang->_styleArray.getStyler(STYLE_WORD3_INDEX);

styleUpdate(w3Style, _pFgColour[2], _pBgColour[2],

IDC_KEYWORD3_FONT_COMBO, IDC_KEYWORD3_FONTSIZE_COMBO,

IDC_KEYWORD3_BOLD_CHECK, IDC_KEYWORD3_BOLD_CHECK,

IDC_KEYWORD3_UNDERLINE_CHECK);

Style & w4Style =

_pUserLang->_styleArray.getStyler(STYLE_WORD4_INDEX);

styleUpdate(w4Style, _pFgColour[3], _pBgColour[3],

IDC_KEYWORD4_FONT_COMBO, IDC_KEYWORD4_FONTSIZE_COMBO,

IDC_KEYWORD4_BOLD_CHECK, IDC_KEYWORD4_ITALIC_CHECK,

IDC_KEYWORD4_UNDERLINE_CHECK);

...

}

要发现这段代码中的错误是非常困难的。但PVS - Studio的耐心和学识:“V525:代码包含相似的块的集合。在行576,580,584,588”中检查项目'7','7','6','7'。让我们缩短的代码,使错误更明显:

styleUpdate(...

IDC_KEYWORD1_BOLD_CHECK, IDC_KEYWORD1_ITALIC_CHECK,

...);

styleUpdate(...

IDC_KEYWORD2_BOLD_CHECK, IDC_KEYWORD2_ITALIC_CHECK,

...);

styleUpdate(...

IDC_KEYWORD3_BOLD_CHECK, IDC_KEYWORD3_BOLD_CHECK,

...);

styleUpdate(...

IDC_KEYWORD4_BOLD_CHECK, IDC_KEYWORD4_ITALIC_CHECK,

...);

此代码最有可能是使用了复制粘贴的方法,导致使用IDC_KEYWORD3_BOLD_CHECK而不是IDC_KEYWORD3_ITALIC_CHECK。您在诊断消息中看到的数字出现这样的宏:

#define IDC_KEYWORD1_ITALIC_CHECK (IDC_KEYWORD1 + 7)

#define IDC_KEYWORD3_BOLD_CHECK (IDC_KEYWORD3 + 6)

最后一个样本具有特别重要的意义,因为它表明,PVS - Studio 分析器同时处理整个大的代码片段,检测重复的结构,并根据启发式方法,认为这代码具有潜在危险。

使用通用分析的好处

静态分析最宝贵的是,你可以在开发初期检测一些错误。一个错误越早检测到,消除它就越容易、快速、便宜。这减少了测试和维护阶段的费用。

静态分析仪处理源代码,检查程序执行中所有可能的方式。因此,您可能会发现在很少使用的代码中或在你打算使用该项目的下一阶段的代码中的错误。

PVS - Studio是一个现代分析仪,没有沉重的过往负担。它积极地发展和学习,检测现在程序员使用Microsoft Visual C + +遇到的错误的新模式。您可能在这一领域帮助我们,并为我们提供你自己发明的诊断规则。在反馈页面给我们发送您的建议。

PVS-Studio静态通用分析规则的更多相关文章

  1. 来试试这个来自静态代码分析工具PVS Studio提供C++的小测验吧

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:来试试这个来自静态代码分析工具PVS Studio提供C++的小测验吧.

  2. pmd静态代码分析

    在正式进入测试之前,进行一定的静态代码分析及code review对代码质量及系统提高是有帮助的,以上为数据证明 Pmd 它是一个基于静态规则集的Java源码分析器,它可以识别出潜在的如下问题:– 可 ...

  3. 常用 Java 静态代码分析工具的分析与比较

    常用 Java 静态代码分析工具的分析与比较 简介: 本文首先介绍了静态代码分析的基 本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBu ...

  4. 11个Visual Studio代码性能分析工具

    软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行代码分析和 ...

  5. C++静态代码分析PreFast

    1历史 Prefast是微软研究院提出的静态代码分析工具.主要目的是通过分析代码的数据和控制信息来检测程序中的缺陷.需要强调的是,Prefast检测的缺项不仅仅是安全缺陷,但是安全缺陷类型是其检测的最 ...

  6. [转载] 常用 Java 静态代码分析工具的分析与比较

    转载自http://www.oschina.net/question/129540_23043 简介: 本文首先介绍了静态代码分析的基本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代 ...

  7. .NET 11 个 Visual Studio 代码性能分析工具

    原文地址 软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行 ...

  8. 【转载】常用 Java 静态代码分析工具的分析与比较

    摘自:http://www.oschina.net/question/129540_23043常用 Java 静态代码分析工具的分析与比较 简介: 本文首先介绍了静态代码分析的基本概念及主要技术,随后 ...

  9. Springboot学习02-webjars和静态资源映射规则

    Springboot学习01-webjars和静态资源映射规则 前言 1-以前我们在IDEA中创建一个项目,添加web依赖包,我们现在是一个web应用,应该在man目录下面有一个webapp文件夹,将 ...

随机推荐

  1. MyBatis根据数组、集合查询

     foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合.foreach元素的属性主要有item,index,collection,open,separator,close.it ...

  2. C#面向对象(OOP)入门—第一天—多态和继承(方法重载)

    面向对象是什么 面向对象是一种基于对象的编程方法,它取代了仅仅依靠方法和流程的编程方式.面向对象的编程语言中,对象(object)其实就是指特定类型.或某个类的实例.面向对象使得编程人员更容易组织和管 ...

  3. linux命令(9):route命令

    查看路由表:route –n //添加到主机的路由 # route add –host 192.168.168.110 dev eth0 # route add –host 192.168.168.1 ...

  4. 字符串截取,SubString

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAk8AAACYCAIAAAByAZqHAAAYgklEQVR4nO2dL28ku5qHTS4ctuTSQf ...

  5. Python+Selenium 自动化实现实例-Xpath捕捉元素的几种方法

    #coding=utf-8import timefrom selenium import webdriverdriver = webdriver.Chrome()driver.get("ht ...

  6. 《java并发编程实战》读书笔记1--线程安全性,内置锁,重入,状态

    什么是线程安全? 当多个线程访问某个类时,不管这些的线程的执行顺序如何,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的. 哈哈书上的解释,还是翻译过 ...

  7. 【hdoj_1085】Holding Bin-Laden Captive![母函数]

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1085 可以这样理解题意:给出1元,2元和5元的三种硬币若干,每种硬币数量给出,现在可以从所有的硬币中,选出 ...

  8. Java工具类-验证码工具

    1.工具类,生成随机验证码字符串 import java.util.Arrays; /** * 工具类,生成随机验证码字符串 * * @version 1.0 * @author * */ publi ...

  9. Flask实战第52天:cms添加轮播图前端代码逻辑完成

    首页我们在模态框中的保存按钮加一个id,这样方便我们选取这个按钮 <button type="button" class="btn btn-primary" ...

  10. ABP+NetCore+Vue.js实现增删改查

    ABP我就不多介绍了,不知道的可以自己百度 本篇开发工具VS2017,数据库SQL SERVER2012,系统Win7 1.去ABP官网下载对应的模板,下载地址:https://aspnetboile ...