基于实时堆栈的程序切片方法

文档序号:6428011阅读:164来源:国知局
专利名称:基于实时堆栈的程序切片方法
技术领域
本发明涉及一种在软件开发过程中进行程序切片的方法,尤其是不仅可以有效处理复杂大型程序,而且可以提高静态程序切片精度的基于实时堆栈的程序切片方法。
背景技术
随着软件规模的日益增大,传统的调试技术不能够有效的处理复杂大型程序。大型应用系统通常有数百行的代码,程序开发人员往往不能够快速的理解程序中的代码,这给程序的调试和维护工作带来了很大的困难。而程序切片是一种程序分析技术,用来将大程序分解成小片段,删除一些与兴趣点不相关的语句,帮助开发人员从中提取感兴趣的部分。其概念和原理由M. Weiser于1979年首次建立。使用程序切片技术,将简化程序分析和理解的难度,加速程序的测试和调试工作,缩短程序的开发和维护时间。程序P中的切片准则可以表示成一个二元组<P,V>,其中P是程序中的一条语句, V是在η处定义或引用的变量。关于该切片准则的切片将包含哪些影响和控制P处变量V 的值得语句。程序切片的计算可以看作一个图的可达性问题,是在系统依赖上找出可达节点。系统依赖图由一个或多个程序依赖图组成。每个过程依赖图表示一个过程内的控制依赖和数据依赖关系。在系统依赖图中,每个过程的依赖图被连接起来,这些边表示过程间的数据依赖和控制依赖。程序切片可以分为静态程序切片和动态程序切片。针对给定的切片准则,两者主要的差异在于进行切片时所需要的信息不同,静态程序切片仅需要程序的静态信息,即源程序;而动态程序切片需要根据程序的输入,记录程序的整个执行轨迹。静态程序切片考虑的是程序所有的执行情况,而动态切片仅考虑程序针对某一输入的特定执行情况。因此,动态切片包含的语句更少,结果更精确些。然而,动态程序切片需要的程序执行轨迹在获取和储存方面都受到时间和空间的限制。优化过的动态切片算法需要数分钟到几十分钟,其前期的准备时间更长。目前大多数的编程语言都支持异常处理机制,在异常处理机制的帮助下,可以提高软件的健壮性,但是异常引起的程序终止也成为一种常见的程序错误。异常通常是由于程序执行过程中,出现了不期望或者错误的状态而引起的。以Java语言为例,异常分为应用异常和实时异常。运行时异常由Java虚拟机抛出,Java编译器不强制要求程序开发人员捕获。如果产生了运行时异常,而程序没有对其进行捕捉,那么程序只能终止。例如空指针引用这类异常,通常发生在多个过程的交互过程中。复杂的控制流及过程调用,使得定位引发异常的原因变得非常复杂。当程序异常终止时,Java虚拟机将会产生堆栈跟踪信息,其中会包括抛出异常的方法以及异常抛出的行号,还有当前调用栈中的所有方法和调用语句所在的行。堆栈跟踪信息可以帮助开发人员修复程序中的错误,然而仅仅通过这些信息,开发人员往往无法精确的找到引发异常的原因。

发明内容
为了克服现有的静态程序切片其精度和实用性低的不足,本发明提供一种基于实时堆栈的程序切片方法,该切片方法可以利用程序异常抛出时保存的堆栈跟踪信息,推测程序的执行轨迹,并在切片的过程中排除与本次执行无关的语句,从而达到减小切片大小、 提高程序切片精度的目的。本发明解决其技术问题所采用的技术方案是该基于实时堆栈的程序切片方法包括如下步骤(1)预处理程序,对程序进行语法、词法分析,生成抽象语法树。(2)根据程序测试用例运行程序,获取实时堆栈输出。(3)将实时堆栈输出信息导入堆栈信息分析器,确定程序语句的执行情况。(4)根据堆栈追踪分析程序中方法的执行情况,将调用程序方法分为三类,可能执行的方法,部分执行的方法,确定没有执行的方法。如果是可能执行的方法,则执行步
骤(5),如果是部分执行的方法,则执行步骤(6),如果是确定没有执行的方法,则执行步骤 ⑵。(5)在程序执行中,这类方法可能被调用过,但是不能确定其中某个语句是否执行过。产生这种情况主要有两点原因,一是仅依靠堆栈追踪信息,对那些已经调用并且正常返回的方法,我们无法确定方法内具体的执行路径;二是由于面向对象语言中多态的特性,即使我们确定某个调用语句执行了,但是其调用的方法可能已经返回,无法确定其调用的是哪个类的方法。在这种情况下,应该对方法中所有语句计算依赖关系,构造相应的程序依赖图,然后进行程序切片操作。(6)在程序执行中,这类方法中有一部分语句可能执行了,而另外一部分语句是可以确定没有被执行的。这类方法必须满足在执行中只被调用一次,并且因异常的抛出而终止,它们一定出现在堆栈追踪里面。我们可以根据该方法内异常终止的节点来确定,方法中哪些节点确定执行过,哪些节点没有执行过。在这种情况下,只对需要执行的那部分方法计算依赖信息,构造相应的程序依赖图,然后进行程序切片操作。(7)在发生异常的执行过程中,这类方法是确定没有被执行过的。这类方法必须满足,在可能执行的方法和部分执行的方法中都没有被调用过,因此它们与本次执行没有任何关系,也就是他们与异常的产生没有关系,在后续切片计算过程中不需要考虑。在这种情况下,不对方法中的语句建立任何计算依赖关系,也不构造程序依赖图,结束程序。所述步骤(5)中的可能执行方法包括如下步骤(5a)计算所有程序中过程内的依赖关系,并且为每个过程构造程序依赖图。程序依赖图是由控制依赖图和数据依赖图组成,表示程序语句间的控制依赖和数据依赖关系。(5b)添加过程调用产生参数输入边,参数输出边,以及总结边,来表示过程间的依赖关系,构造出被切片程序的系统依赖图。(5c)添加形式参数节点(Formalin)和形式输出节点(Formal_0ut)节点。对于每个函数调用点,需要添加相应的实际参数节点(Actualin)和实际输出节点(Actual out),并添加从实际参数节点到形式参数节点的参数输入边和从形式输出到实际输出节点的参数输出边用来表示参数的传递。并且添加从实际参数节点到实际输出节点的概括边。(5d)首先不沿parameterjut边对系统依赖图进行第一遍遍历,然后第二次遍历时不沿parameter_in和call边,两步遍历过程中标记的节点即为切片。(5e)程序切片完成后,结束程序。所述步骤(6)中的部分执行的方法包括如下步骤(6a)计算部分程序中过程内的依赖关系,并且为每个过程构造程序依赖图。程序依赖图是由控制依赖图和数据依赖图组成,表示程序语句间的控制依赖和数据依赖关系。(6b)添加过程调用产生参数输入边,参数输出边,以及总结边,来表示过程间的依赖关系,构造出被切片程序的系统依赖图。(6c)添加形式参数节点(Formalin)和形式输出节点(R)rmal_out)节点。对于每个函数调用点,需要添加相应的实际参数节点(Actualin)和实际输出节点(Actual out),并添加从实际参数节点到形式参数节点的参数输入边和从形式输出到实际输出节点的参数输出边用来表示参数的传递。并且添加从实际参数节点到实际输出节点的概括边。(6d)首先不沿parameter^ut边对系统依赖图进行第一遍遍历,然后第二次遍历时不沿parameter」!!和call边,两步遍历过程中标记的节点即为切片。(6e)程序切片完成后,结束程序。所述步骤(7)中的确定没有执行的方法包括如下步骤(7a)不进行程序模型的遍历,自动跳过确定没有执行的方法,结束程序。本发明的有益效果是,该基于实时堆栈的程序切片方法极大的提高了静态程序切片在软件开发中的实时性,提高了静态程序切片的精度,减少了切片结果包含的语句的数量,有效的缩短了程序开发和维护的时间。


下面结合附图和实施例对本发明作进一步说明。图1是本发明依据堆栈跟踪进行程序切片的流程。图2是本发明依据堆栈跟踪进行方法分类的算法。
具体实施例方式为了便于利用实时堆栈信息对程序进行切片,我们首先对切片过程的依赖关系进行定义定义1控制依赖如果程序中语句u和w满足以下三个条件,那么就称w直接控制依赖于u ;1)从u到w之间存在一条路径P ;2)从P上除u,w之外的每个节点V,节点w都是它的后向必经节点;3)节点w不是节点u的后向必经节点。定义2控制依赖图G (N,E),N表示程序中语句对应的节点集合,E表示边集,其中每条边U — W表示W控制依赖于U。定义3数据依赖如果程序中,语句u对变量ν进行了定义,w引用了变量ν的值, 并且U到W之间存在一条路径,该路径上没有对V进行重新定义,那么就称W关于变量V直接数据依赖于W。定义4数据依赖图G (N,E),N表示程序中语句对应的节点集合,E表示边集,其中每条边U — W表示W直接数据依赖于U。在图中,该基于实时堆栈的程序切片方法包括如下步骤(1)预处理程序,对程序进行语法、词法分析,生成抽象语法树。(2)根据程序测试用例运行程序,获取实时堆栈输出。(3)将实时堆栈输出信息导入堆栈信息分析器,确定程序语句的执行情况。(4)根据堆栈追踪分析程序中方法的执行情况,将调用程序方法分为三类,可能执行的方法,部分执行的方法,确定没有执行的方法。如果是可能执行的方法,则执行步
骤(5),如果是部分执行的方法,则执行步骤(6),如果是确定没有执行的方法,则执行步骤 ⑵。(5)在程序执行中,这类方法可能被调用过,但是不能确定其中某个语句是否执行过。产生这种情况主要有两点原因,一是仅依靠堆栈追踪信息,对那些已经调用并且正常返回的方法,我们无法确定方法内具体的执行路径;二是由于面向对象语言中多态的特性,即使我们确定某个调用语句执行了,但是其调用的方法可能已经返回,无法确定其调用的是哪个类的方法。在这种情况下,应该对方法中所有语句计算依赖关系,构造相应的程序依赖图,然后进行程序切片操作。(6)在程序执行中,这类方法中有一部分语句可能执行了,而另外一部分语句是可以确定没有被执行的。这类方法必须满足在执行中只被调用一次,并且因异常的抛出而终止,它们一定出现在堆栈追踪里面。我们可以根据该方法内异常终止的节点来确定,方法中哪些节点确定执行过,哪些节点没有执行过。在这种情况下,只对需要执行的那部分方法计算依赖信息,构造相应的程序依赖图,然后进行程序切片操作。(7)在发生异常的执行过程中,这类方法是确定没有被执行过的。这类方法必须满足,在可能执行的方法和部分执行的方法中都没有被调用过,因此它们与本次执行没有任何关系,也就是他们与异常的产生没有关系,在后续切片计算过程中不需要考虑。在这种情况下,不对方法中的语句建立任何计算依赖关系,也不构造程序依赖图,结束程序。所述步骤(5)中的可能执行方法包括如下步骤(5a)计算所有程序中过程内的依赖关系,并且为每个过程构造程序依赖图。程序依赖图是由控制依赖图和数据依赖图组成,表示程序语句间的控制依赖和数据依赖关系。(5b)添加过程调用产生参数输入边,参数输出边,以及总结边,来表示过程间的依赖关系,构造出被切片程序的系统依赖图。(5c)添加形式参数节点(Formalin)和形式输出节点(R)rmal_out)节点。对于每个函数调用点,需要添加相应的实际参数节点(Actualin)和实际输出节点(Actual out),并添加从实际参数节点到形式参数节点的参数输入边和从形式输出到实际输出节点的参数输出边用来表示参数的传递。并且添加从实际参数节点到实际输出节点的概括边。(5d)首先不沿parameter^ut边对系统依赖图进行第一遍遍历,然后第二次遍历时不沿parameter」!!和call边,两步遍历过程中标记的节点即为切片。(5e)程序切片完成后,结束程序。所述步骤(6)中的部分执行的方法包括如下步骤(6a)计算部分程序中过程内的依赖关系,并且为每个过程构造程序依赖图。程序依赖图是由控制依赖图和数据依赖图组成,表示程序语句间的控制依赖和数据依赖关系。
(6b)添加过程调用产生参数输入边,参数输出边,以及总结边,来表示过程间的依赖关系,构造出被切片程序的系统依赖图。(6c)添加形式参数节点(Formalin)和形式输出节点(R)rmal_out)节点。对于每个函数调用点,需要添加相应的实际参数节点(Actualin)和实际输出节点(Actual out),并添加从实际参数节点到形式参数节点的参数输入边和从形式输出到实际输出节点的参数输出边用来表示参数的传递。并且添加从实际参数节点到实际输出节点的概括边。(6d)首先不沿parameterjut边对系统依赖图进行第一遍遍历,然后第二次遍历时不沿parameter」!!和call边,两步遍历过程中标记的节点即为切片。(6e)程序切片完成后,结束程序。所述步骤(7)中的确定没有执行的方法包括如下步骤(7a)不进行程序模型的遍历,自动跳过确定没有执行的方法,结束程序。
权利要求
1.基于实时堆栈的程序切片方法,其特征在于包括如下步骤(1)预处理程序,对程序进行语法、词法分析,生成抽象语法树;(2)根据程序测试用例运行程序,获取实时堆栈输出;(3)将实时堆栈输出信息导入堆栈信息分析器,确定程序语句的执行情况;(4)根据堆栈追踪分析程序中方法的执行情况,将调用程序方法分为三类,可能执行的方法,部分执行的方法,确定没有执行的方法;如果是可能执行的方法,则执行步骤(5),如果是部分执行的方法,则执行步骤(6),如果是确定没有执行的方法,则执行步骤(7);(5)对方法中所有语句计算依赖关系,构造相应的程序依赖图,然后进行程序切片操作;(6)只对需要执行的那部分方法计算依赖信息,构造相应的程序依赖图,然后进行程序切片操作;(7)不对方法中的语句建立任何计算依赖关系,也不构造程序依赖图,结束程序。
2.根据权利要求1所述的基于实时堆栈的程序切片方法,其特征是所述步骤(5)中的可能执行的方法包括如下步骤(5a)计算所有程序中过程内的依赖关系,并且为每个过程构造程序依赖图,程序依赖图是由控制依赖图和数据依赖图组成,表示程序语句间的控制依赖和数据依赖关系;(5b)添加过程调用产生参数输入边,参数输出边,以及总结边,来表示过程间的依赖关系,构造出被切片程序的系统依赖图;(5c)添加形式参数节点(Formalin)和形式输出节点(R)rmal_out)节点,对于每个函数调用点,需要添加相应的实际参数节点(Actualin)和实际输出节点(ActUal_0Ut),并添加从实际参数节点到形式参数节点的参数输入边和从形式输出到实际输出节点的参数输出边用来表示参数的传递,并且添加从实际参数节点到实际输出节点的概括边;(5d)首先不沿parameter^ut边对系统依赖图进行第一遍遍历,然后第二次遍历时不沿parameterjn和call边,两步遍历过程中标记的节点即为切片; (5e)程序切片完成后,结束程序。
3.根据权利要求1所述的基于实时堆栈的程序切片方法,其特征是所述步骤(6)中的部分执行的方法包括如下步骤(6a)计算部分程序中过程内的依赖关系,并且为每个过程构造程序依赖图,程序依赖图是由控制依赖图和数据依赖图组成,表示程序语句间的控制依赖和数据依赖关系;(6b)添加过程调用产生参数输入边,参数输出边,以及总结边,来表示过程间的依赖关系,构造出被切片程序的系统依赖图;(6c)添加形式参数节点(Formalin)和形式输出节点(Formal_out)节点,对于每个函数调用点,需要添加相应的实际参数节点(Actualin)和实际输出节点(ActUal_0Ut),并添加从实际参数节点到形式参数节点的参数输入边和从形式输出到实际输出节点的参数输出边用来表示参数的传递,并且添加从实际参数节点到实际输出节点的概括边;(6d)首先不沿parameter^ut边对系统依赖图进行第一遍遍历,然后第二次遍历时不沿parameterjn和call边,两步遍历过程中标记的节点即为切片; (6e)程序切片完成后,结束程序。
4.根据权利要求1所述的基于实时堆栈的程序切片方法,其特征是所述步骤(7)中的确定没有执行的方法包括如下步骤(7a)不进行程序模型的遍历,自动跳过确定没有执行的方法,结束程序。
全文摘要
本发明涉及一种基于实时堆栈的程序切片方法,该程序切片方法利用程序异常抛出时保存的堆栈跟踪信息,推测程序的执行轨迹。该程序切片方法极大的提高了静态程序切片在软件开发中的实时性,提高了静态程序切片的精度,减少了切片结果包含的语句的数量,有效的缩短了程序开发和维护的时间。
文档编号G06F11/36GK102214141SQ201110188810
公开日2011年10月12日 申请日期2011年7月2日 优先权日2011年7月2日
发明者姜淑娟, 张红昌, 靳蓉 申请人:中国矿业大学
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1