一种基于控制流图的内存泄漏自动修复方法
【技术领域】
[0001] 本发明涉及基于控制流图的技术,具体为一种能够自动修复C语言内存泄漏的错 误的方法,属于软件测试领域。
【背景技术】
[0002] (一)错误修复相关技术
[0003] 近年来有很多关于错误修复的研究。例如,一些研究人员[1' 2'3]试图利用一些方法 自动修复一般类型的错误。所使用的方法通常使用所违反的正确条件,修改代码以满足这 些条件。该正确条件来源于测试用例 [2'3],或诸如前置条件和后置条件的断言[1]。在所述 正确条件被说明后,通常使用演化算法来给出修复。例如,在Arcuri和Yao的工作 [2]中, 计算机程序和测试用例同时演化,并相互影响。Weimer等人[3]使用遗传算法的一种扩展形 式来演化程序变体。另外,Weiet等人 [1]在状态图中基于类的布尔查询来使用状态的抽象 表示。以上这些技术使用的正确条件通常是不适当的,并且很少保证正确性。另外,说明修 复内存泄漏的正确条件(如测试用例或断言)也是困难的。
[0004] 还存在一些修复特定类型错误的方法。例如,Jin等人[4,5]的方法自动修复多种 并发性错误。这些方法中没有关于内存泄漏的修复。
[0005] 修复可能是不好的,并引入新的错误。Gu等人[6]形式化了不佳修复的问题,并且 定义了修复的两个维度。"覆盖"维度衡量了正确修复所有错误的广度,而"破坏"维度衡量 修复后的计算机程序与原有行为的偏差。在本发明中,我们能够确保修复的正确性,也就是 避免了"破坏"这个维度,同时尽可能提高"覆盖"维度。
[0006] (二)内存泄漏相关技术
[0007] 有静态和动态两种方法来处理内存泄漏。静态方法主要用于内存泄漏的检测 [7'8'9'1(U1'12' 13]。大多数检测算法只报告内存泄漏发生的位置。因为在大多数情况下,分配 内存和发生内存泄漏的位置分布在完全不同的位置,开发人员要进行修复仍然需要很多工 作。即便在Fastch eCk[1°]中,它给出了内存分配的泄漏路径,这个信息仍然不足以提供修 复。而且,所有这些方法都有假阳性错误,这让开发人员很难依赖这些方法来自动修复内存 泄漏。
[0008] 另外一种处理内存泄漏的静态方法是关于Java的内存管理[14'15' 16]。这些方法在 Java字节码中插入专门的释放语句,以减少需要被垃圾回收器扫描的引用的数量并提高运 行时性能。这些方法与本发明有相似之处,即通过静态分析插入释放语句。但是,很难把这 些方法应用于C语言。这是因为,首先,在C语言中,必须保证没有双重释放,而在Java中不 存在这个问题。而且,不能仅仅通过在这些技术中增加功能来解决双重释放的问题,因为双 重释放与搜索策略紧密相关,必须重新设计算法。其次,现有技术都是直接修改Java字节 码,而在C语言中必须修改源代码,因而可读性是一个重要的方面。因此,现有工作中的很 多技术不能被使用。例如,频繁地插入临时变量在源代码级别是不能被接受的。最后,Java 有垃圾回收器,任何未被释放的内存可以被其安全回收。而在C语言中,每个错误都是潜在 重要的错误,而且报告是否完全修复是重要的。上述技术都没有提供这些功能。
[0009]处理内存泄漏使用最广泛的动态方法是垃圾回收机制[17'18' 19' 2°],它给运行时带来 开销。也有动态检测内存泄漏的方法[21'22' 23'24'25'26],它提供了在运行时泄漏的内存分配的 位置。然而,类似于静态检测技术,这些技术都无法提供帮助快速修复的有用信息。
[0010] 一些研究人员意识到修复内存泄漏的重要性,并尝试从多个方面解决这个问题。 LEAKP0INT [27]试图提供帮助定位修复位置的信息,该信息不仅报告内存分配的位置,它也 报告内存引用丢失的位置或被最后一次使用的位置。然而,修复泄漏需要考虑所有路径,这 个信息并不足以保证自动生成修复。Rayside和Mendel [28]使用对象所有权的分析来寻找 和修复垃圾(内存被引用但从未被使用)。但是,正像名称所指出的,这个技术只能给出统计 报告,并不是自动修复。Xu等人 [29]提出了使用三个不同等级的知识来帮助不了解计算机 程序的开发人员快速发现错误的根源。这份工作也不能自动修复内存泄漏。上述方法均依 赖动态分析,引入了运行时开销。
[0011] 也存在关于其它内存相关错误的研究。例如,Caballero[3CI]等人使用动态方法检 测释放后使用和双重释放的错误,Demsky和Rinard [31]使用基于规约的方法来自动修复数 据结构。这些工作与本发明不同,不处理内存泄漏,并且使用了动态方法。Fischer等人 [32] 提出基于语义的方法来修复文件打开/关闭和队列上溢/下溢错误。该方法关注语义,并 没有给出方法的有效性或高效性。
【发明内容】
[0012] 本发明的目的是提供一种基于控制流图的内存泄漏自动修复技术。本发明能够保 证修复的正确性,修复正确性定义如下:
[0013] 给定分配好的内存块c,一个正确的内存泄漏的修复是将一条释放语句s插入计 算机程序中,使得下面三个条件在任何一个s被执行的路径被满足 :
[0014] l.c在s之前被分配,s释放c。
[0015] 2.没有其它释放c的释放语句。
[0016] 3.在s的执行后没有其它c的引用,也就是说,c在插入点后死亡。
[0017] 除了正确性,还要求尽早释放,这样当我们不需要使用内存块时,就将其释放。
[0018] 本发明的技术方案如下:
[0019] 一种基于控制流图的内存泄漏自动修复方法,应用于计算机程序的内存泄露检测 和自动修复,包括如下步骤(参见图4):
[0020] 第一步:制作计算机程序的控制流图,根据现有技术[10],即可将计算机程序转 换为控制流图;
[0021] 第二步:根据所述控制流图进行内存泄露检测和修复,包括:
[0022] _在控制流图上进行指针分析,并标注出分配结点和内存释放结点;
[0023]_内存泄漏检测:将控制流图中的边分为一定发生内存泄漏、可能发生内存泄漏 和一定不发生内存泄漏三类;
[0024] _内存泄漏修复:分析变量的活跃度,在控制流图中一定发生内存泄漏的边添加 修复代码;
[0025] 第三步:利用在控制流图中记录的代码位置信息,将添加到图中的修复代码映射 回原计算机程序代码中。
[0026] 优选的,所述的内存泄漏自动修复方法,包括如下步骤:
[0027] 1)构造计算机程序的控制流图;
[0028] 2)在控制流图上进行指针分析;同时,在控制流图中标注出分配结点、内存释放 结点;指针分析用于分析控制流图中指向同一块内存的指针;分析时,对于指针赋值语句, 将赋值语句左侧被赋值的指针加入右侧赋值的指针所在的别名集合,并将该左侧指针从原 集合中删掉;对于其他语句不进行操作;分析的结果是在控制流图中的每个结点前、后,都 提供指针的别名集合;
[0029]3)内存泄漏检测:将控制流图中的边分为一定发生内存泄漏、可能发生内存泄漏 和一定不发生内存泄漏三类;
[0030] 4)内存泄漏修复:在控制流图中一定发生内存泄漏的边添加修复代码;添加修复 代码有三个条件:a)在该边存在指向该内存块的指针;b)该边是"一定发生内存泄漏"这一 类的边;c)在该边指向该内存块的指针是不活跃的;迭代运行步骤3)和4),直到不能再提 供更多修复为止;
[0031] 5)将控制流图映射回代码:利用在控制流图中记录的代码位置信息,将添加到控 制流图中的修复代码映射回原计算机程序代码中。
[0032] 本发明的有益效果:开发者可以使用本发明所述的方法自动修复计算机程序的内 存泄漏,而不必担心修复错误或引入新错误。
【附图说明】
[0033] 图1内存泄漏代码示例。图1中,第1行分配了内存,但在第27和29行计算机程 序返回时没有释放内存,因而发生内存泄漏。本修复工具可在26、27行之间,以及27、28行 之间加入修复,释放array指向的内存块。
[0034] 图2示例代码对应的控制流图示例。其中,椭圆代表计算机程序中的语句,有向边 代表计算机程序控制流的流向。有向边上的和"〇"分别代表分支条件被满足和不被满 足。根据图2的控制流图可以分析内存泄漏发生的路径并进行修复。
[0035] 图3示例控制流图(图2)的内存泄漏检测结果示例。每条边被标记以表示属于哪 种分类。DF表示一定不发生内存泄漏的边,PS表示可能发生内存泄漏的边,UN表示一定发 生内存泄漏的边。
[0036] 图4本发明所述方法的流程示意图。
【具体实施方式】
[0037] 本发明提供技术方案如下:
[0038] 首先,基于计算机程序的控制流图,把计算机程序的分析转化为对控制流图的分 析;进而在控制流图上给出修复;最后把控制流图上的修复转换回代码。具体描述如下:
[0039] 1、控制流图构造:根据现有技术[1°],将计算机程序转换为控制流图;例如,