基于流敏感上下文敏感指向图的内存泄漏检测方法技术

技术编号:4234043 阅读:226 留言:0更新日期:2012-04-11 18:40
本发明专利技术公开了一种基于流敏感上下文敏感指向图的内存泄漏检测方法,要解决的技术问题在于:一方面提高内存泄漏检测的精确度,一方面保证内存泄漏效率。技术方案是先对源代码做语法分析和词法分析,生成中间文件;对中间文件计算流敏感、上下文敏感的指针信息,生成流敏感和上下文敏感的指向图;利用流敏感和上下文敏感的指向图检测被检测程序的每个过程内是否存在内存泄漏,获取MOD信息,再利用流敏感和上下文敏感的指向图检测程序过程间的内存泄漏;最后判断新得到的数据流事实是否矛盾以检测是否有内存泄漏。采用本发明专利技术能提高内存泄漏检测的效率和精确度。

【技术实现步骤摘要】

本专利技术主要涉及计算机程序中内存泄漏的静态检测方法,尤其是一种利用流敏感、上下文敏感的指向图来检测程序中内存泄漏的方法。
技术介绍
(:、0++等语言中都支持指针的使用,这可以使代码变得灵活、简洁,但是由此引发 的内存错误也是各类错误中比较难以分析、追踪和消除的。内存泄漏就是一种典型的错误。 在编写程序阶段,编程人员往往很难确定程序在运行的时候需要多少内存,因此动态内存 分配是必不可少的操作。指针和动态内存分配提供了方便、灵活的内存操作机制。 一块内 存的分配者同时也承担着释放它的责任。如果只是不断的分配,而没有相应的释放操作,程 序将占用越来越多的内存,最终会耗尽计算机系统的内存,导致计算机系统崩溃。对于大型 的、需要长时间运行的程序——例如操作系统——来说,内存泄漏错误有可能是致命的。但 内存泄漏的检测是一项比较困难的工作,因为与其他错误不同,内存泄漏没有明显的、易于 观察的错误行为,无法回收的内存并不能立刻对程序以及系统的运行产生影响。因此,内存 泄漏的检测是一项十分有意义而又面临着重大挑战的任务。内存泄漏有多种不同的定义,这取决于如何定义一块内存单元的生命周期。若一块内存在生命周期结束时仍未被释放,则认为有内存泄漏发生。而生命周期的定义主要可以分为以下三种基于引用、基于可达性和基于活跃性的定义等。基于引用的生命周期是 指如果一个计算机内存单元没有被任何指针所指向,则生命周期结束。目前检测内存泄漏的方法主要有动态方法和静态方法两大类。动态方法是在程序的运行过程中收集相关信息,判断是否有内存泄漏发生,但该检测方法过于依赖程序运行所用的测试用例的质量,并且由于程序实际上的执行路径可能有无穷多条,一般情况下无法产生足够多的测试用例以检查所有可能的执行路径,也就难以检测到所有的错误。静态方法不需要动态执行程序,可以找到所有可能的内存泄漏错误。采用静态方法进行检测的工具有很多,包括PREfix, SATURN, LCLint和Metal等,但该方法的主要缺陷是误报率比较高。因此,如何在保持检测效率的同时降低误报率,是静态方法的研究热点之一。 现有的围绕内存泄漏的静态检测主要有基于形态分析的检测方法、基于指针向图的检测方法和基于特殊模型的检测方法等。 Hackett和Rugina提出了一种利用形态分析(shape analysis)来检测内存泄漏 的方法。该方法可以对程序的存储形态做局部推理,而不是做全局推理。它使用了形态抽 象的技术,根据变量的指向信息把所有的内存划分为若干个相互独立的区域。针对每个区 域做独立的分析,而与其他区域无关,这提高了分析的效率。另外,还可以通过参数来设置 分析精度,精度越高,相互独立的内存区域就越多,计算复杂性随之升高。该方法的不足在 于其健壮性不够,某些表达式或者特定语句顺序会对内存区域的划分产生重大影响,从而 导致算法效率或者精度的急剧降低。 0rlovich和Rugina提出了一种基于指针分析的数据流分析方法,该方法以需求驱动的方式执行。传统的穷尽式方法以整个程序作为检测对象,提供程序中所有与该内存 泄漏相关的信息;而需求驱动方式则只检测所关心的特定语句,只提供与这些语句相关的 信息。Orlovich等人的方法利用反证法来判断内存泄漏是否存在,它以流不敏感、上下文不 敏感的指向图作为输入,甚至不需要程序的完整代码,只检测代码段的内存泄漏错误。由于 流不敏感、上下文不敏感的精度较低,有可能导致该方法产生较多的误报。 Heine和Lam提出了基于ownership模型的内存泄漏检测方法。该方法为动态分 配的内存指定了持有者,持有者是一个指针或者结构中的指针域。每个动态分配的而尚未 被释放的内存都有唯一的持有者,它的责任是释放该内存或者把持有者的身份转移到另一 个指针或者指针域中。该方法最终转化为一个线性约束方程组的求解问题,通过方程组解 的存在与否来判断是否有内存泄漏发生。这种方法的不足之处在于只有"固定位置(fixed location)"才能够充当持有者。对于一些比较复杂的表达式和操作,比如链表、树等,基于 ownership模型的方法就难以处理或者产生误报。因为在这些操作中,可能要求动态分配的 内存来充当持有者。 综上所述,有多种不同的内存泄漏检测方法,每种方法都有各自的特点与适用范 围,也有不足之处。针对很多C程序中指针及动态内存分配语句较少的事实,需求驱动的检 测是一种比较适合而又有效的技术,且这种方法也表现出了较好效率。但是,在流不敏感的 指向图中,由于其不考虑语句的执行顺序,很多不同的内存位置被视为相同,且合并为一个 内存位置,这也造成了不同的指针被合并。在基于引用的内存泄漏的定义中,这样的合并会 导致把多个引用视为一个引用,从而产生误报,降低了方法准确性。
技术实现思路
本专利技术要解决的技术问题在于针对指针和动态内存分配操作的特点,提供一种 基于流敏感、上下文敏感指向图的内存泄漏检测方法,以需求驱动方式保证方法的效率,同 时充分利用流敏感、上下文敏感指向图所提供的信息,提高静态检测内存泄漏方法的精确度。 本专利技术的技术方案为结合流敏感、上下文敏感指向图和需求驱动的方式,独立地 检查某条语句是否会引发内存泄漏错误。通过逐一检查每条指针赋值语句,报出程序中所 有可能的内存泄漏错误。在检查的过程中,采用后向数据流分析方法,逆着程序控制流的方 向做计算,同时根据语句的类型以及相关的指向图,只检查程序中与当前关注问题相关的 语句,避免不必要的计算。 具体技术方案为 第一步,利用编译器(典型的有GCC、SUIF、LLVM等)对被检测程序做词法分析、语 法分析,生成编译器自身支持的中间文件。 第二步,使用编译器自带的指针分析器或其他独立的指针分析器对中间文件做流 敏感、上下文敏感的指针分析,在程序控制流图中的每个代表程序语句的结点上生成指向 图。指向图是程序运行时指针变量或者结构中的域指针之间指向关系的一种表示形式,它 是一个有向图,图中每个结点代表一个位置集合。位置集合是内存的一种抽象表示,一个位 置集合代表程序运行时的一个或者多个内存。在指向图中,如果从结点u到v之间有一条 有向边,则u中存在一个元素所代表的内存中保存的地址指向v中某一元素所代表的内存。生成指向图的步骤如下 2. 1获取指向图中的结点。每个指针变量都代表一个位置集合,并作为结点在指向 图中出现,其名称就是变量名字;对于动态分配的内存,每一条分配语句产生一个结点,所 有同一语句分配的动态内存使用一个结点来表示,用语句所在的行数作为结点的名字。 2. 2逐一分析程序中的语句,每条指针赋值语句产生一个指向关系,即赋值语句中 指针变量指向表达式的值,由此产生指向图的一条边。 2. 3合并指向图中的指向关系若某一条语句s有多个直接前驱语句(即该语句 执行完后下一步可直接执行s)可直接抵达该语句,则合并这些前驱语句传递过来的指向 关系所代表的边。此步骤操作使得指向图成为流敏感的。 2.4在程序的过程间生成指向关系。通过计算形参实参的值,在程序的入口处合并过程在不同调用上下文中所产生的指向关系。此步骤使得指向图成为上下文敏感的。 2. 5判定当前语句是否导致新的指向关系出现,若出现,转2. 3 ;本文档来自技高网
...

【技术保护点】
一种基于流敏感上下文敏感指向图的内存泄漏检测方法,其特征在于包括以下步骤:第一步,利用编译器对被检测程序做词法分析、语法分析,生成编译器自身支持的中间文件;第二步,使用编译器自带的指针分析器或其他独立的指针分析器对中间文件做流敏感、上下文敏感的指针分析,在程序控制流图中的每个代表程序语句的结点上生成指向图,指向图是程序运行时指针变量或者结构中的域指针之间指向关系的一种表示形式,它是一个有向图,图中每个结点代表一个位置集合;位置集合是内存的一种抽象表示,一个位置集合代表程序运行配语句、释放语句、返回语句这四种类型语句生成数据流事实的初始化信息:3.1.3.1对于赋值语句e↓[0]=e↓[1],生成初始化信息的方法为:init(e↓[0]=e↓[1],G)=(l,hold(l,G)∩ll(e↓[0],G),{e↓[0]},{e↓[1]}),其中,hold(l,G)代表指向图G中指向l的那些内存位置;ll(e↓[0],G)代表表达式e↓[0]在指向图G中的左值;3.1.3.2对于动态内存分配语句e↓[0]=malloc(),初始化信息的获取方法为:init(e↓[0]=malloc(),G)=init(e↓[0]=NULL,G);3.1.3.3对于释放语句free(e),如果e指向一个指针,则检查这个指针是否是某一内存块的唯一持有者,这种情况下采用3.1.3.1的方法为赋值语句*e=NULL生成初始化信息;如果e指向一个结构,则逐一检查该结构中所有的指针域,对于每一个指针域n,采用3.1.3.1的方法为赋值语句e→n=NULL生成初始化信息;3.1.3.4对于返回语句returne,初始信息的获取分为两个步骤:第一个步骤是在返回语句之前加入一系列的赋值语句v↓[1]=NULL;...;v↓[m]=NULL,其中v↓[i]是该过程中所有的局部变量,1≤i≤m,然后用3.1.3.1的方法获取这些赋值语句的初始信息;第二个步骤是对于调用该过程的语句,实际上是把e赋给该调用语句中赋值号左端的表达式,因此把该调用语句看作是一个赋值语句,按照3.1.3.1赋值语句的方式来获取初始信息;3.2利用流敏感和上下文敏感的指向图,从当前程序语句处反向找到在其之前执行的前驱语句s,针对s的类型采用下述方法逐步生成新的数据流事实:3.2.1s是赋值语句e↓[0]=e↓[1]时:3.2.1.1如果一个表达式的左值位置集合和访问位置集合中的元素...

【技术特征摘要】

【专利技术属性】
技术研发人员:王戟马晓东董威徐厚峰刘万伟
申请(专利权)人:中国人民解放军国防科学技术大学
类型:发明
国别省市:43[中国|湖南]

网友询问留言 已有0条评论
  • 还没有人留言评论。发表了对其他浏览者有用的留言会获得科技券。

1