通用分析

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. TensorFlow计算模型—计算图

    TensorFlow是一个通过计算图的形式来表述计算的编程系统.其中的Tnesor,代表它的数据结构,而Flow代表它的计算模型.TensorFlow中的每一个计算都是计算图上的一个节点,而节点之间的 ...

  2. WdatePicker做出onchange效果

    WdatePicker({onpicking: function (dp) {if (dp.cal.getDateStr() != dp.cal.getNewDateStr()) { Func(dp. ...

  3. java的collection集合

    # 原创,转载请先留言 1.集合的由来 数组的长度是固定的,当需要增加或减少元素时需要对数组重新定义,太麻烦了.java内部给我们提供了集合类,能存储任意对象,长度可以改变的,随着元素的增加而增加,随 ...

  4. java中String的内存位置

  5. MySQL-数据操作

    阅读目录 一 介绍 二 插入数据INSERT 三 更新数据UPDATE 四 删除数据DELETE 五 查询数据SELECT 回到顶部 一 介绍 MySQL数据操作: DML ============= ...

  6. Oracle SQL中实现indexOf和lastIndexOf功能

    Oracle SQL中实现indexOf和lastIndexOf功能 https://www.2cto.com/database/201305/210470.html

  7. 如何在SQL Server中的SELECT TOP 中使用变量

    语法   [ TOP (expression) [PERCENT] [ WITH TIES ] ] 注意:expression 是在一对圆括号内的,而之后又有如下的例子 在 TOP 中使用变量 以下示 ...

  8. Rsync+Inotify 搭建实时同步数据

    1.安装软件包 # yum install inotify-tools # yum -y install rsync 2.同步机器相互添加信任 [root@host-10-0-100-106 ~]# ...

  9. php5.5 安装

    1.php安装 wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo yum install zl ...

  10. mp4文件格式解析(转载)

    mp4文件格式解析 原作:http://blog.sina.com.cn/s/blog_48f93b530100jz4b.html 目前MP4的概念被炒得很火,也很乱.最开始MP4指的是音频(MP3的 ...