基于变异技术的软件故障修复方法研究

时间:2022-09-25 03:18:11

基于变异技术的软件故障修复方法研究

摘 要 程序的可维护性和可靠性已经成为软件产业发展的突出难题,如何快速锁定故障,如何有效修复软件已经成为当前软件工程实践中最重要的活动之一。基于变异的程序故障修复技术,在阐述C程序表达式故障的方法中,利用变异修复机制来辅助修复程序故障,并通过实例故障来验证方法的有效性。

关键词 程序软件 变异技术 故障定位 修复方法

计算机技术的发展,特别是软件技术的广泛应用,越来越多的程序在出现故障后带来了更多维护性难题。软件测试技术的发展,主要针对软件程序运行可靠性问题,从程序故障的锁定及修复中来提升软件质量。美国标准与技术研究所NIST调查显示,软件程序故障修复的成本每年达到595亿美元,约占总GDP的0.6%。程序故障修复作为软件工程实践中的重要内容,在软件修复程序中耗时、费力,且完全依赖于软件开发人员的专业知识和行业经验。这种现象不仅加长了软件开发周期,也阻碍了软件产业的快速发展。因此,积极从软件程序修复技术及理论研究中,就软件行业程序故障修复问题进行探讨,并从软件故障修复实践中来开发自动化修复工具,以改善软件程序故障修复的缺陷。

一、当前软件程序故障修复现状及方法研究

从软件技术开发实践来看,软件程序故障是软件工程的重要内容,当前软件开发人员在面临程序故障修复时,多以手工方式来进行故障定位和修复,使得程序开发周期较长,成本较高。国内外对软件故障修复理论的研究也取得了一定进展,特别是在内存管理、数据结构修复及特定数据类型的故障提示中也取得一定成绩。Dallmeier等人通过对软件运行与失败的差异分析,利用回归测试用例来减少程序修复后产生的新问题;Perkins等人通过不变式监控程序的方法,就汇编级程序错误进行自动检测和修复。然而,这两种方法主要针对条件表达式或监控器软件相关的错误修复。Arcuri等人首次以遗传编程自动修复方法,根据程序规模的扩大,利用遗传编程搜索方法来进行修复,较为适宜单个函数的修复;Weimer等人为了缩小进化算子的搜索空间,采用抽象语法树先对程序进行抽象,再通过基于遗传的编程方法就C语言程序和汇编语言程序进行修复。我国学者何加浪等人在Weimer研究基础上,利用不变量约束来对搜索空间进行简化,并针对测试过程难以覆盖所有功能需求,提出成功测试用例学习的不变量约束来解决该难题;成功测试用例与失败测试用例所执行的路径不同,对于程序故障及修复方法也不一致,反而限制了程序修复的类型;另外,该方法在修复过程中还产生大量无关冗余的代码转换;遗传算法本身的非稳定性,在程序本身的变化中也存在适应性问题。

二、基于变异技术的软件故障修复原理及步骤

(1)基于变异技术的软件故障修复原理。传统基于变异的测试技术是对已知程序,根据变异算子来得到一批程序故障变异体,利用这些变异体来对测试用例集T进行测试。而新的基于变异技术的程序故障修复技术,则是将之作为故障程序,根据变异算子来选择故障程序的变异,从而得到一批变异体,利用已知的测试用例集来对这些变异体进行验证,以得到程序故障修复目标。在制定变异体是否修复软件故障时,首先需要定义变异体的标准,即对于变异体执行完成后的输出结果与期望不一致。任何一个被放弃的变异体都不能是故障程序的正确修复版本,原因是这些变异体曾导致测试用例执行失败。相反,如果一个变异体顺利通过测试用例,说明本变异体被故障程序进行正确修复。通过对这些潜在修复版本的分析,可以帮助程序开发人员得到期望的程序。

(2)故障程序修复实施步骤。基于变异技术的故障程序修复方法,其具体实施步骤表示如下:一是要确定故障类型,利用程序变异技术对某类特定的程序故障进行测试,在修复之前,首先要明确变异修复程序的故障类型。程序设计人员在对程序常见故障类型进行分析,并从发生概率高且危害大的故障类型进行修复,有助于提升软件的修复效果,降低软件开发成本。二是选择合适的变异算子,对于变异算子是基于变异技术的故障修复方法,也是产生变异体的基础。通过导入多元化变异算子,能够从不同类型的故障测试中进行修复,最大化的提升变异体的生成。程序故障修复方法应该能满足不同类型的故障测试,高效的修复方法需要变异修复的代价尽可能小。因此,在对变异算子的设计上,要从执行效率和变异体修复效果上来针对不同程序故障类型进行修复。三是设定变异修复停止条件。在进行变异技术故障修复执行过程中,对于某些特定的程序故障,并不是所有程序故障都能够得到修复,只有当产生并检查一定数量的变异体后,如果找不到对应的修复版本的变异体,则会提示:继续还是停止;如果选择继续,则进行再次修复版本变异体的查找,否则直到找到变异体被检查出,修复程序并不停止。通常情况下,对于修复对象为大型程序软件时,对于变异体的数量要求也较大,如果选择继续则会浪费系统资源,因此需要设置一个停止条件。三是变异故障程序,对于所设计的变异算子本身,由于设置的变异修复停止条件不同,对故障程序进行变异产生变异体时,可以先利用故障定位技术来对故障程序进行明确,再利用故障检测结果来选择修复程序故障,从而降低修复代价。四是确定修复变异体版本,并通过变异故障程序返回到产生新的变异体,以检查和确定故障程序的潜在修复版本。

三、C语言程序故障修复方法

(1)C语言程序故障类型划分。C语言软件开发常用语言,在对C语言程序进行故障修复测试中,需要对所提供的故障系统类型进行分析,总的来说归结为四类:即内存故障,以内存资源释放、分配错误、函数返回值错误、非法指针应用错误等;条件表达式错误,通常表现在If、While、For结构开头的条件表达式,其错误主要与关系运算符、逻辑运算符及边界条件故障有关;变量赋值错误,其故障主要发生在变量赋值语句中,如某些运算符或边界赋值错误而引发的变量赋值故障;语句冗余或缺失类错误,随着程序工作流程和设计流程的差异而导致程序执行失败。

(2)C语言变异算子的设计。变异算子是程序故障修复的关键,也是基于变异测试技术最常用的程序变异体。变异算子在设计上主要从算术运算符的变异、关系运算符的变异,以及逻辑运算符的变异中来完成。针对程序中常用的运算符,能够从运算符错误引起的变量赋值故障或条件表达式故障中,对包含算术、关系、逻辑运算符的程序语言进行测试。针对程序设计中的条件表达式、变量赋值故障,以及语句冗余或赋值缺失等故障,从变异算子的设计上,能够实现对每一类特殊故障类型的修复,如多一些子类型故障进行修复,就需要从程序发生错误的概率中进行针对性设计,优先为故障发生率高的程序设计相应的变异算子。

(3)变异算子处理方法。针对不同类型的变异算子,在进行变异故障修复中,对于运算符变异,从常用运算符如算术运算符、关系运算符、逻辑运算符、自增/自减运算符、位操作符、赋值运算符等,利用替换运算符进行变异,能够修复的故障类型主要有变量赋值故障和条件表达式故障。如对于条件表达式中的变异,针对可疑程序语句的条件表达式,从整体取反进行变异,或者通过整体加1或减1来进行变异;对于边界值变异,针对可疑语句中的For循环,通过初始量增1或减1进行变异;对于初始化变量赋值偏差错误,可疑通过赋值方法进行修复;对于常量浮点变异,针对可疑语句进行变异成等值的浮点型常量,如float a=1/2;假设程序对a的期望值为0.5,根据C语言语法,可疑从分子分母整型常量赋值中来引发变量赋值故障,以完成对错误的修复。对于类型扩展变异,通过对可疑程序语句中的float、int等关键字,将其变异为高一级类型,以修复由精度缺失带来的变量赋值故障。

(4)变量修复停止条件。从程序故障修复方法中,必须要对不能修复的故障类型,以及找不到潜在修复版本的情况进行终止修复,这就需要从变异修复中设定某一停止条件。如当变异修复所使用的代价高于某一限值时,仍未找到潜在修复版本的变异体就会返回程序终止。简言之,对于某一变异体从产生到执行完所用的代价为e,若在找到潜在修复版本时需要检查n个变异体,则此次修复代价为;可见,对于变异修复代价主要取决于n值大小,也就是修复过程所检查的变异体数量。

(5)潜在修复版本的确定。基于变异技术的程序故障修复,是对程序在执行过程中对变异体进行所有测试用例后还活着,则说明该变异体为潜在修复版本。同样,在变异修复程序设计上,还应该至少包括一个失败测试用例,与潜在修复版本具有不同的输出结果。基于变异技术的故障修复方法,并没有对所有测试用例的数量进行限制,当每次测试用例集中的测试用例数量过多时,则会带来更大的验证变异体的代价。因此,可以对测试用例集的选取进行确定,以避免变异体修复所花费的代价过多。程序设计人员可以从测试用例集的选择上,先对测试用例集进行优化,再进行故障程序变异修复。

参考文献:

[1]陈翔,顾庆.变异测试:原理、优化和应用[J].计算机科学与探索, 2012(12).

[2]周改云,张国平,吕琼帅,黎远松.利用智能控制流方法的嵌入式软件故障检测[J].电子技术应用,2015(10).

(作者单位:河南财政税务高等专科学校)

上一篇:从事实到规范:犯罪化立法原则层次论 下一篇:基本养老保险基金信托的证成与运行保障