程序动态切片技术研究

摘 要

程序切片技术是一种重要的程序分析技术,广泛应用于程序的调试、测试与维护等领域。程序切片主要通过寻找程序内部的相关特性,从而分解程序,然后对分解所得的程序切片进行分析研究,以此达到对整个程序理解和认识的目的。而动态程序切片主要是指在某个给定输入的条件下,源程序执行路径上所有对程序某条语句或兴趣点上的变量有影响的语句。

面向对象技术仍是目前软件开发方法的主流,其中封装、继承、多态、并发等特征都为程序的理解与分析提出了新的问题。本文在程序的分析评测中引入使用基于依赖图的程序切片技术,实现其切片功能,解决在程序理解、程序复杂性度量、程序转换和评测中遇到的问题。

本文采用一种基于依赖图的面向对象的动态程序切片方法,核心算法是以静态程序的程序依赖图为基础,先从程序依赖图里提取出对应给定执行历史的数据依赖节点和控制依赖节点,使用图可达性算法,计算得出可达语句集,从而获得所需的动态切片,对程序进行理解分析。 

【关键词】:数据依赖、控制依赖、程序依赖图、程序切片、动态切片 

Abstract

Program slicing is an important program analysis techniques, widely used in debugging, testing and maintenance and other fields. Program slicing within the main 

program by finding the relevant features to break down program, and then proceeds to the decomposition of the analysis of program slicing, in order to achieve the 

overall objective of understanding and awareness programs. The dynamic program slice is the main input in a given condition, the source of all the program execution 

path of a statement or point of interest on the variable impact statement. 

    Object-oriented software development method is still the mainstream, including encapsulation, inheritance, polymorphism, concurrency and other features are the 

understanding and analysis of the program raised new problems. In this paper, the introduction of evaluation procedures for the analysis of dependence graph-based 

program slicing techniques to achieve its slice function to solve the program comprehension, program complexity metrics, program transformation and evaluation of 

problems encountered.

This paper, a dependency graph based on dynamic program slicing of object-oriented approach, the core algorithm is the program that rely on a static picture shows 

the base, starting with the program dependence graph to extract the corresponding implementation of the history of a given node and the control dependence data 

dependence Nodes, using the graph accessibility algorithm calculated statements set up to obtain the necessary dynamic slicing, program understanding of the analysis.

【Key words】:DD,CD,PDG,Program Slicing,Dynamic Slicing 

目  录

摘 要 I

Abstract II

第一章 绪 论 

第一节 课题研究目的和意义 

第二节  研究内容和本文结构 

第二章 程序切片技术 

第一节 程序切片技术的概述 

第二节 切片技术的应用 

第三章 动态程序切片技术 

第一节 动态切片法产生的背景及现有算法 

第二节 动态程序切片实现算法 

第四章 动态程序切片系统设计 

第一节 系统概要设计 

第二节 详细设计 

第三节 实例分析 

第五章 系统的实现环境和运行结果的分析 

第一节 开发与运行环境 

第二节 系统输出 

第六章 结束语 

第一节 本文的主要工作 

第二节 展望 

致谢 

参考文献 

附录 

附录A核心代码 

附录B 英文原文 

附录C英文翻译 

附录D

第一章 绪 论

第一节 课题研究目的和意义

软件危机曾经是软件界甚至整个计算机界最热门的话题为了解决这场危机,软件从业人员、专家和学者做出了大量的努力。现在人们已经逐步认识到所谓的软件危机实际上仅是一种状况,那就是软件中存在故障,正是这些故障导致了软件开发在成本、进度和质量上的失控。故障是软件的属性,而且是无法改变的,因为软件是由人来编写的,所有由人做的工作都不会是完美无缺的。

软件测试就是“为了发现故障而执行程序的过程”,其根本目的就是尽可能地消除软件中的故障,使得软件在正式投入使用之前,软件中的故障密度达到尽可能低或者可以接受的程度。软件测试是软件生命周期中的重要一环,在当前的软件开发过程中发挥着越来越重要的作用。统计表明,在典型的软件开发项目中,软件测试工作量往往占软件开发总工作量的40%以上;在软件开发的总成本中,用在测试上的开销要占到50%左右。

软件测试的实质是根据软件开发各阶段的规格说明和程序的内部结构精心选取一批测试数据,形成测试用例,并用这些测试用例去驱动被测程序,观察程序的执行结果,验证实际运行结果与期望结果是否一致,然后做相应的调整。可见,测试数据生成是软件测试的核心与关键。

白盒测试(结构测试)一般是根据被测程序的内部结构设计测试用例,具有很强的理论基础。这种结构测试要求对被测程序的结构特性做到一定程度的覆盖。路径覆盖是一种相对比较强的覆盖标准,要求生成足够多的测试数据,尽可能覆盖所有程序路径。但是,实际中往往会出现这样的情况:多个测试用例执行的是同一条程序路径,而有的程序路径则从未被执行过。因此,探讨一种有效的手段,以辅助基于路径的测试数据生成,有着很现实的意义。

第二节  研究内容和本文结构

本文在理解M.Weiser的切片算法的基础上,根据H.Agrawai等人提出的基于静态程序依赖图的算法,编写程序,最终实现切片系统。并对程序切片进行测试分析。

本文的第一章简要介绍本课题研究的背景、意义以及关于切片系统的实现目标;第二章主要介绍程序切片的技术概述和应用发展;第三章则是动态程序切片的具体算法设计;第四章关于动态程序切片系统设计的介绍;第五章则是本系统的开发环境和运行结果分析;第六章则是对本文的总结以及展望。 

第二章 程序切片技术

第一节 程序切片技术的概述

程序切片技术是M.Weiser在他的1979年的博士论文中首次提出的一种程序分解技术。主要通过寻找程序内部的相关特性,从而分解程序,然后对分解所得的程序切片进行分析研究,以此达到对整个程序理解和认识的目的。后来在1981年和1984年,M.Weiser博士又发表了两篇论文对这种技术进行推广和完善。后来切片技术引起了研究者们广泛的关注,由于它起到了其他技术无可替代的作用,因此可以说是程序分解领域的一场大变革,无论在程序的分析和理解、调试还是测试和维护过程都起到了巨大的作用,另外切片技术还在硬件描述语言和其他规约语言以及形式化模型等方面的分析有至关重要的作用,因此它的研究具有极其重要的理论和实际意义。

M.Weiser博士首先在1979年定义了程序切片的概念:程序中的某个输出只与这个程序的部分相关语句以及控制谓词有关系,因此如果删除其他的语句或者控制谓词将对这个输出没有任何影响。也就是说,对于一个特定的输出,源程序和对于删除不相关的语句和控制谓词后所得的程序是作用相同的。其形式化定义如下:

把满足如下两个条件的切片称为M.Weiser切片:第一,一个程序切片需要对应一个切片准则,用<n,V>表示,其中n指程序中的某个兴趣点,一般指一条语句,V表示在这条语句使用的变量的集合。第二,程序P的切片s可以通过在P中删除零条或者多条语句后得到,且保证程序P和所得的切片S关于切片准则的作用是相同的。

当时,M.Weiser博士把只与某个输出相关联的语句和控制谓词构成的程序称之为源程序的静态切片。由此可见,一个程序的切片大多数是源程序的一个子集,这个概念准确的说其实就是程序切片的一个核心思想。

后来随着研究的发展,研究者们对M.Weiser博士程序切片的概念进行了扩展,由于程序切片不一定都是可执行的,因此又包含了不可执行的切片思想,这也是一种静态切片,这样就丰富和发展了程序切片的内涵。随后,KorelLaski又提出了动态切片的概念,它只考虑程序的某个特定执行情况,程序中的信息如数组、指针和循环依赖关系都可以在程序执行时动态确定。因此,动态切片与静态切片相比结果更加的准确。

在程序切片技术二十几年的发展过程中主要经历了如图2.1所示的四个阶段

图2.1 程序切片技术的发展历程

第一个阶段是基于数据流方程的切片阶段,这其实就是M.Weiser博士提出切片概念的阶段,主要使用了基于控制流图的数据流方程来计算程序切片。

第二个阶段是基于依赖图的程序切片阶段,这一阶段产生了对程序切片提出了很多新的概念和算法。首先,Ottenstein等人在提出了基于程序依赖图的图可达性算法,并可以计算过程内后向程序切片,接着又提出了前向切片的概念和算法,以及基于依赖图的两步遍历图的可达性算法。最后KorelLaski提出了动态切片的概念和算法。

第三个阶段是面向对象的程序切片阶段,这一阶段是伴随着面向对象的高级程序语言的发展而产生,在1996M.J.Horrald等人首次使用类依赖图来扩展系统依赖图,从而表示面向对象的c++程序,并通过改进的两步遍历图可达性算法来计算程序的切片。随后Christon Steindl在1999年通过对各种数据流以及控制流的计算,提出了面向对象程序切片计算的解决方法,起到了很重要的作用。

最后一个阶段是程序切片变体阶段,这一阶段出现了各种程序切片的变体形式,例如砍片、削片、层次切片等等,这些都极大地促进了程序切片技术的迅速发展。

通过上面程序切片的发展阶段可以看出程序切片有很多种,主要有静态切片和动态切片,前向切片和后向切片,规约切片,削片,砍片,无定型切片等等。这些种类其实本质都是一致的,也是随着发展阶段一步步演化而来的。

由于本文主要使用到动态切片,因此这里主要对与之相关的静态切片和动态切片以及前向切片和后向切片作简要介绍。后文中将详细分析动态切片。

如果在计算程序切片时不考虑程序的具体输入,计算对某个感兴趣点影响的语句和谓词集合,这样得到的切片就是静态切片。其切片准则为<n,V>。

如果在计算程序切片时考虑程序的某个具体输入,然后计算程序P在这个特定输入。的条件下所有影响V在n点的值的语句和谓词集合,这样得到的切片就是动态切片。其切片准则为<n,V,>。

后向切片是指构造一个集合aflect(v/n),使得这个集合由所有影响v在n点的语句和谓词组成。例如如果在测试程序时发现了其中的某个错误,我们就需要知道是前面哪条语句或者哪个谓词表达式导致了这个错误,这样也就需要计算程序的后向切片。

前向切片正好相反,是指构造一个集合affect (v/n),使得这个集合由受到n点的变量V的值的影响的所有语句和谓词构成。前向切片也有广泛的应用,如果对程序的bug修改以后,我们可能想知道这点修改是否会带来其他的副作用,也就是说这点修改会影响后面的哪些语句,这就需要计算程序的前向切片。

第二节 切片技术的应用

由于是程序切片,与程序有关,因此毫无疑问在软件的编码和调试阶段用处是最明显的。尤其在调试阶段,当出现错误时通过程序切片可以快速对程序中的错误进行定位,这样引起错误的代码就被限定在这个程序切片里,从而方便了程序员调试。对于软件度量,可以利用软件体系结构的切片技术验证体系结构是否正确,从而保证按照这个体系结构设计出的软件是正确可靠的,同时在设计阶段利用模块间的切片技术也可以设计出高内聚低祸合的模块,从而为软件的重用性起到大的作用。此外,程序切片技术还应用于软件安全方面和软件测试方面。在软件测试中主要用于回归测试,在软件开发过程中,当系统修改了一处或多处后需要对整个软件重新测试,以防止修改不会带来其他模块的问题、一周此工作量是非常大的,而且也会消耗大量的人力物力。由于在回归测试时,软件只有小部分代码被修改,因此只要通过程序切片技术获得源程序中受到修改代码影响的所有其他代码,这样只要对这些受影响的代码进行测试就可以了,这样就给回归测试带来了极大的方便。本文主要采用程序切片技术来自动生成测试用例,也属于程序切片的一个应用之一。

程序切片技术有着广泛的应用场合,主要应用如图2.2所示:

图2.2 切片技术的应用 

第三章 动态程序切片技术

第一节 动态切片法产生的背景及现有算法

本文主要研究的是动态切片程序,所以在这里对动态切片再进行细致的介绍。顾名思义,动态切片法是与静态切片法相对应的,它由静态切片法演化而来。在1988年,B.KorelJ.Laski首次提出动态切片的概念,主要由基于数据流方程的静态切片扩展而来。他们认为动态切片是源程序的一个可以执行的子集,在对某个变量输入相同的变量值时切片和源程序将会执行相同的程序路径。后来,1990年,H.AgrawalJ.Horgan又提出了新的动态切片的思想:动态切片主要包含在某个给定输入的条件下,源程序执行路径上所有对程序某条语句或兴趣点上的变量有影响的语句。这两种概念的不同之处在于,前者产生的动态切片比较大,常常包含一些多余不必要的语句,而后者产生的切片较小,而且更加的精确。动态切片法相对与静态切片法有很多优点,首先,由于它只考虑程序在某个特定输入条件下的情况,所以很多如数组下标、指针、循环依赖关系等程序信息可以在动态执行时动态确定,所以相比静态切片结果会更加的精确。其次,在某些场合下,例如在程序调试过程中,处理一次bug时通常只关注在某个输入下执行的路径行为,而不会关注变量所有可能输入导致的行为,所以动态切片比静态切片更加的方便,大大的减少了切片的大小,调试也因此大大缩小了范围。当然,动态切片法也有缺点,由于动态切片需要追踪程序的执行行为和执行历史,所以空间代价较高。

从动态切片概念的产生发展至今,主要有以下几个动态切片算法。

1.H.AgrawalJ.Horgan1990年提出的四种计算动态切片的方法。第一种方法是以静态程序的程序依赖图为基础,先从程序依赖图里提取出对应给定执行历史的一个投影图,再利用静态切片法对投影图进行操作,即使用两次图可达性算法,从而获得所需的动态切片。但是这种方法由于常常包含多余的节点,对同一个变量来说某一个节点可能存在很多由该变量引出的数据依赖边,因此计算出的动态切片不够精确。第二种方法类似第一种方法,也是以静态程序的程序依赖图为基础,在程序执行时首先在程序依赖图中标记出产生的依赖边,然后在图中沿着这些标记的边进行遍历,这样由所有标记经过的节点对应的语句集合就构成了动态切片。这种方法改进了第一种方法产生多余节点的问题,但是缺点是却不能处理包含循环结构的源程序。第三种方法不再基于静态依赖图,而是重新提出了一个新图,即动态依赖图:即为执行历史中语句每一次的出现创建一个节点并只对这一次出现有依赖关系的语句添加引出的依赖边。对于不同的程序执行历史,同一个程序有不同的动态依赖图。当建立了程序的动态依赖图之后,先找到执行历史中变量的最后定义所在的节点,然后在图中使用二次图形可达性算法,从而获得变量的动态切片。

2.B.Korels.Yalamanchih1994年提出的前向计算的动态切片算法。算法的主要思想为把程序看成是若干个基本块,然后通过执行到基本块的出口时判断这个基本块是否应该包含在动态切片中。这种方法虽然不需要建立动态依赖图,因此节省了大量的执行代价和执行空间。

3.Goswami和Mall在2002年提出的基于压缩的动态程序依赖图的算法。算法的主要思想为首先建立程序的控制依赖子图,然后再通过程序的执行序列和数据流信息建立程序的数据依赖子图,最后生成动态切片

第二节 动态程序切片实现算法

一、相关定义:

这里主要对算法相关的术语和定义作一下介绍,后文将不再解释。动态切片准则用三元组 (v)表示,s为程序中的某条语句,s表示在第k步执行语句Sv是程序变量或变量集,为输入数据。

定义1:基本模块:指程序中一组连续执行的语句,在模块的开始处控制流

进入,在模块的结束时离开,而且不能在模块的执行过程中终止或者出现分支。对于基本模块,控制流只能从模块的入口进入,从模块的出口离开。

定义2:控制流图   (Control Flow GraphCFG):控制流图CFG是一个有向图,该有向图的节点是一个包括唯一入口和出口的基本模块,如果控制流可以从一个模块流入另外一个模块,则这两个模块之间有一条边。可以用四元组表示为G=(NE, EntryExit),其中N是节点的集合,也就是基本模块的集合,E是边的集合,每一条边为一个有序节点对<ninj>,表示从ni执行完以后开始立即执行njEntry表示子程序的入口,Exit表示子程序的出口,程序从入口节点Entrynk的节点序列<n1,n2n3nk>是一条执行路径,其中n1为入口Entry节点,<nini+l> Ei k。

定义3:DEF:CFG中节点n定义变量的集合,记为DEF[n]

定义4:USE:CFG中节点n使用变量的集合,记为USE[nl

定义5:后必经节点:如果从节点n到程序出口节点Exit的每一条路径都经过节点m,则称mn的后必经节点,记为nm

定义6:控制依赖(CD):CFG中,设和是其中的两个节点,如果满足以下三个条件,则称控制依赖于,,记为CD(,)

(1)节点到节点之间有一条可执行路径A

(2)A上除了和外的每一个节点n,节点n:都是它的后必经节点。

(3)节点不是节点的后必经节点。

定义7:控制依赖节点集(CDNC):CDNC()表示当前执行的第k步语句s的控制依赖节点集合。

定义8:数据依赖(DD):CFG中,设和是其中的两个节点,v为一个

变量,如果满足以下三个条件,则称关于变量v数据依赖于,记为口D(,,v)

(1)节点,对变量v进行了定义,即v

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值