RSS
热门关键字:  数据挖掘  数据仓库  商业智能  人工智能  搜索引擎

C/C++内存问题检查利器——Purify(1)

来源: 作者:unkonwn 时间:2004-12-13 点击:

一、           引言

  数据挖掘研究院

我们都知道软件的测试(在以产品为主的软件公司中叫做

  数据挖掘研究院

 

 

数据挖掘研究院

二、           Purify简介

  数据挖掘研究院

C/C++的软件开发中,没有任何一种工具可以让你的应用程序避免引入内存问题,但是我们可以使用诸如Purify这样的工具对已经做好了的程序进行内存问题的检查。Purify的强大之处是可以找到应用程序中全面的内存问题,并可以和GDB/DBX等调试器以配合使用,让你对你的内存错误一目了然。

数据挖掘研究院

 

Purify是一个Run-Time的工具,也就是说只有在程序运行过程中,根据程序的运行情况来查看在某种运行条件下程序是否有内存上的问题,它可以在一个非常复杂的程序中查找内存错误,包括那种多进程或多线程的程序,它也可以进行测试。

 

数据挖掘研究院

Purify对程序中的每一个内存操作都进行检测,并对精确报告内存出现错误的变量和语句,以提供出现错误原因的分析。Purify主要检测的是下面这些内存错误: 数据挖掘研究院

 

数据挖掘研究院

l         数组内存是否越界读/写。

l         是否使用了未初始化的内存。 数据挖掘研究院

l         是否对已释放的内存进行读/写。

l         是否对空指针进行读/写。 数据挖掘研究院

l         内存漏洞。 数据挖掘实验室

  数据挖掘研究院

在软件工程中,以我的经验而言,最好是在编码阶段时就使用Purify检测内存存问题,一直到交给测试人员测试。请相信我,在一个大型的C/C++软件产品中,即使检测出了内存问题,离真正地解决它还有一定的距离,所以为了让这个“距离”不算太远,最好还是在功能模块完成时就进行Purify的内存检测。

 

一般而言,在软件测试中,首要的是软件的功能测试,然后是反面案例测试,再而是压力测试。就我个人经验而言,使用内存检测工具的阶段应该是编码阶段、模块合并后、以及程序逻辑测试完成以后,直到产品发布前,也要做一个内存测试。 数据挖掘研究院

  数据挖掘研究院

要使用Purify这个工具很简单,首先在你安装好了的Purify的目录上你会看到两个Shell脚本:purifyplus_setup.csh(对应于C-Shell purifyplus_setup.sh(对应于标准Shell)。你先执行一下这两个脚本,以便让Purify设置好一些环境参数,如:

数据挖掘研究院

> source purifyplus_setup.csh 数据挖掘研究院

 

数据挖掘研究院

而对于你的程序而言,你需要这样使用:

数据挖掘研究院

    > purify cc –g –o myProgram myProgram.c

     > purify cc –g –c –o myLib.o myLib.c

数据挖掘实验室

 

数据挖掘研究院

就这么简单,然后你只要运行你的程序就行了,Purify会向你提交一份内存问题的报告清单,以供你分析。Purify使用的是OCIObject Code Insertion)技术,它会在你的目标程序中插入一些它自己的函数,这些函数主要都是内存检测的语句,这些语句将会放置在程序中所有,内存操作之前,一旦在程序运行时发现内存问题,Purify所插入的这些语句就会向你报告。一般来说,所有的内存检测工具都是这样工作的。 数据挖掘研究院

 

数据挖掘研究院

当被Purify编译过的程序运行时,Purify会弹出一个图形界面的窗口,来向你报告内存问题。如下所示:

 

数据挖掘研究院

 

点击三角符号后将出现更为详细的信息:

数据挖掘研究院

 

数据挖掘研究院

 

Purify在报告内存问题的时候,可以指出源程序中哪个地方出现内存问题,但对于内存泄漏而言,它只能指出出现问题的内存是哪一块,也就是指出内存是在哪里被分配的,而不是指出内存泄露是如何发生的。这是比较合乎情理的,所以,即使你知道那块内存发生了泄漏,你也不一定能找到究竟在什么时候发生的。当然,如果你让Purify配合GDB一起使用,那么要找到这种问题的根本原因,也不是什么困难的事情。

数据挖掘实验室

 

三、           示例

假设我们现在有这样一段程序:hello.c

数据挖掘研究院

#include <stdio.h>

#include <malloc.h> 数据挖掘研究院

 

static char *helloWorld = "Hello, World"; 数据挖掘实验室

  数据挖掘研究院

main()

{

   char *mystr = malloc(strlen(helloWorld)); 数据挖掘实验室

  数据挖掘研究院

   strncpy(mystr, helloWorld, 12); 数据挖掘实验室

   printf("%s ", mystr);

} 数据挖掘研究院

  数据挖掘实验室

很明显,这段程序中有内存上的错误,假设我们疏忽了这些错误,当我们使用Purify进行测试时,我们会发现这段程序中的内存错误在Purify下很容易就被找出来了。首先,我们要做的是使用Purify编译这段程序: 数据挖掘实验室

 

数据挖掘研究院

> purify gcc -g -o hello hello.c 数据挖掘研究院

Purify 2003.06.00 Solaris 2 (32-bit) Copyright (C) 1992-2002 Rational Software Corp. 
All rights reserved. 

Instrumenting: cckc6pUD.o  Linking 数据挖掘研究院

  数据挖掘研究院

记得加上“-g”的选项,不然,purify不能显示源程序。好了,现在在当前目录下产生了可执行文件——hello,在运行hello之前,我们还得注意,执行被Purify编译过的程序,有可能会出现X-Windows,所以请注意设置DISPLAY环境,如果你是在WindowsTelnet客户端下执行,那么你可以在Windows下装一个叫做Exceed的工具软件,它可以方便地把X-Window显示在你的Windows桌面上)

  数据挖掘研究院

好了,我们现在执行hello程序,就可以看到下面的一个窗口: 数据挖掘研究院

  数据挖掘研究院

数据挖掘研究院

  数据挖掘实验室

我们可以看到Purify的报告中有两个内存错误,一个是ABRArray Bounds Read)——数组越界读,一个是12个字节的Memory Leaked,展开小三角符号,我们可以看到更为详细报告:

  数据挖掘研究院

数据挖掘研究院


展开
ABR错误后,我们可以看到,ABR错误的产生是由printf产生的,而产生错误的内存是mystr。通过观察,我们马上可以发现为会什么会出现ABR错误,原因是C/C++中的字符串都是以“”结尾的,而我们分配字符串时,应该要比实际长度多一,以存放结束符,而我们以后面调用的strncpy只拷贝了字符串的有效内容,并没有在字符串最后加上一个结束符。而系统调用printf输出字符串内容直至遇到结束符,所以当其访问到12个长度时,还没有发现结束,于是继续向下访问,于是就出现了ABR错误。

数据挖掘实验室


数据挖掘研究院

 

数据挖掘研究院

  数据挖掘研究院

好了,让我们再来看看Memory Leaked的报告信息: 数据挖掘研究院


 

数据挖掘研究院

我们可以看到,Purify指出了那块内存出现了内存泄露,泄露了多少个字节。通过Purify的报告,再加上我们对C/C++基础的了解,我们立马知道mystr是在堆上分配的内存,所以必须要我们自己手动释放,查看程序,我们发现我们忘了free ( mystr )

数据挖掘研究院

 

好了,现在我们可以根据Purify报告修改我们的程序了:

数据挖掘研究院

 

数据挖掘研究院

#include <stdio.h>

数据挖掘研究院

#include <malloc.h>

  数据挖掘研究院

static char *helloWorld = "Hello, World";

  数据挖掘实验室

main()

{ 数据挖掘研究院

       char *mystr = malloc(strlen(helloWorld)+1); 数据挖掘研究院

  数据挖掘研究院

   strncpy(mystr, helloWorld, 12);

数据挖掘实验室

   mystr[12]=””;

  数据挖掘研究院

   printf("%s ", mystr);

数据挖掘研究院

   free(mystr); 数据挖掘实验室

}

  数据挖掘实验室

现在,我们再用Purify重新编译我们的程序,然后运行,我们可以看到Purify会报告没有任何的内存问题。其实,使用Purify很简单,在后面,我将对Purify的各种常用特性做比较全面的阐述。

  数据挖掘研究院

四、           内存问题一览

下面是Purify所能检测到的内存信息表: 数据挖掘实验室

  数据挖掘实验室

内存信息

描述 数据挖掘研究院

错误等级

数据挖掘研究院

ABR 数据挖掘实验室

Array Bounds Read 数组越界读 数据挖掘研究院

3

数据挖掘研究院

ABW

数据挖掘研究院

Array Bounds Write 数组越界写 数据挖掘实验室

2 数据挖掘实验室

BSR

数据挖掘研究院

Beyond Stack Read 越栈读 数据挖掘研究院

3 数据挖掘研究院

BSW

Beyond Stack Write 越栈写 数据挖掘研究院

最新评论共有 0 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
匿名?