没有合适的资源?快使用搜索试试~ 我知道了~
理论计算机科学电子笔记177(2007)75-89www.elsevier.com/locate/entcsJava程序R. Caballero1,2FacultadeInform'ticaUniversidad Complutense de Madrid西班牙马德里C.赫尔曼斯3InstitutfurürWirtschaftsinformatikUniversitütMuünster,GermanyH. Kuchen库钦1,4InstitutfurürWirtschaftsinformatikUniversitütMuünster,Germany摘要在本文中,我们提出了适用于声明式调试的思想,面向对象的语言Java作为替代传统的跟踪调试器中使用的命令式语言。 声明式调试器构建一个合适的计算树,其中包含有关在错误计算期间发生的方法调用的信息。然后导航树,询问用户问题,以便将每个方法的预期语义与其实际行为进行比较,直到找到错误的方法。 该技术已在一个可用的原型中实现。我们评论的几个新的问题时,使用这种调试技术,传统上适用于声明性语言,一个完全不同的范式,并提出了几个可能的改进和未来的工作线。保留字:面向对象语言(Object-Oriented Languages)。1介绍封装的概念已成为当今软件开发过程中的一个关键思想。应用程序被视为不同封装的组件1本作者得到了项目TIN 2005 -09207-C 03 -03和S-0505/TIC/0407的资助2电子邮件地址:rafa@sip.ucm.es3电子邮件地址:hermannc@wi.uni-muenster.de4电子邮件地址:kuchen@uni-muenster.de1571-0661 © 2007 Elsevier B. V.在CC BY-NC-ND许可下开放访问。doi:10.1016/j.entcs.2007.01.00576R. Caballero等人理论计算机科学电子笔记177(2007)75软件组件,其中每个组件又可以由其它简单组件组成这里的封装意味着程序员只需要知道每个组件做什么(语义),而不用担心如何完成(实现)。面向对象的语言,如Java [16],就是基于这个概念,允许定义灵活,可扩展和可重用的软件组件,从而节省时间,避免最终程序中的错误。虽然这种将软件视为组件的组合的观点是成功的,并且在设计和实现阶段被广泛使用,但它对软件开发周期的后期阶段(如测试和调试)几乎没有影响。事实上,调试器通常包含在现代的IDE语言(如Java)中,是复杂的跟踪器,它们不利用组件关系。声明式调试,也称为算法调试,是由E. Y. Shapiro在[14]中作为逻辑编程范式的跟踪调试器的替代方案,其中复杂的执行机制使传统的这个想法后来被用于其他声明式编程范式,如函数式编程[11]和函数逻辑编程[3声明式调试器在用户在测试程序时发现一些意外行为时启动然后调试器构建一个对应于产生初始症状的计算的树。该树的每个节点对应于某个子计算的结果,并且具有相关联的程序代码片段,即产生结果所需的代码片段。节点的子节点对应于那些子计算的结果,这些子计算是获得父结果所必需的。特别地,树的根对应于主计算的结果。用户在树中导航,查找包含无效结果但其子节点生成有效结果的节点。这样的节点被认为是有缺陷的节点,并且其相关联的代码片段被指出为错误的,因为它从其子节点的正确输入结果产生了错误的输出结果。本文将声明式调试的思想应用到面向对象语言Java中。从一些错误的计算开始,我们的调试器在被调试的程序中定位一个错误的方法。用户在调试会话期间的任务被简化为检查计算期间发生的某些方法调用所产生的结果的有效性。因此,我们的工具抽象出每个方法的实现细节,从方法的预期语义和程序的结构中推断出错误的方法为了提高工具的效率,我们建议使用测试用例生成器,如GlassTT [8,9,10]。该工具使用一些覆盖标准将每个方法的可能输入值划分为等价类对等价类的任何代表的方法调用的正确/不正确行为将导致该类的其他成员的方法的有效性/无效性。因此,调试器可以使用此信息,以便从单个用户答案中推断出多个节点的状态虽然仍处于研究的早期阶段,但我们认为这种改进可以大大减少在R. Caballero等人理论计算机科学电子笔记177(2007)7577调试会话。在声明性编程之外使用声明性调试的想法并不新鲜。1989年N.Shahmehri和P.Fritzson在[13]中提出了第一个建议,由同一作者在[5]中进一步发展。在这项工作中,声明式调试器的命令式语言Pascal的。该方案的主要缺点是计算树是通过程序转换获得的,这限制了调试器的效率。我们方法的不同之处在于。这些较早时提出的建议包括:• Java是一种比Pascal复杂得多的语言声明式调试程序,包括对象,因此对象状态介绍了新的困难,还没有被研究到现在,我们在本文中解决• Java等现代语言为实现声明式调试器提供了新的可能性在我们的案例中,我们的原型实现基于Java平台架构(JPDA)[7]。JPDA具有基于事件的体系结构,并使用方法进入和方法退出事件来生成计算树。结果是一个更有效的工具。最近的相关工作[6]提出了一个Java声明式调试器,它保存了Java计算期间发生的大多数相关事件数据库可以由用户查询,以了解程序的状态(变量,线程等)。在执行的不同时刻,以便推断错误所在的位置。这两个建议之间的主要区别是,我们的调试器只集中在方法调用的逻辑,存储在一个结构化的方式(计算树),允许调试器推断出错误的方法从用户的答案。在下一节中,我们将介绍声明式调试思想在Java程序中的应用。第3节介绍了使用测试用例生成器的想法,以减少用户在发现bug之前必须回答的问题的数量。在第4节中,我们讨论了原型的局限性。最后,本文提出了一些结论和未来的工作.2声明性的在本节中,我们将介绍应用于面向对象语言Java的声明式调试的思想及其原型实现。2.1计算树我们首先定义调试器使用的计算树的结构。由于该工具的目的是检测Java程序中的错误方法,因此树的每个节点都包含有关正在分析的计算期间发生的某些方法调用的信息。设N是计算树中包含某个方法f的方法调用信息的节点。然后N的子节点将对应于在f的定义中发生的方法调用,这些方法调用在计算存储在N的结果期间执行。例如考虑78R. Caballero等人理论计算机科学电子笔记177(2007)75方法f定义为:public int f(int a){ if(a)return g(a); else return h(a);}然后,任何与f的方法调用相关联的节点都将有一个子节点,该子节点将对应于对g(如果参数为正)或h(否则)的方法调用。因此,正如我们将在下一小节的示例中看到的,在循环语句中发生的方法调用可以产生几个子节点。计算树的这种结构保证有缺陷的节点,即具有有效子节点的无效节点,将对应于错误的方法,并且因此所提出的调试技术是正确的。然而,在Java计算树中检查节点的有效性这是因为除了返回结果之外,面向对象语言中的方法可以更改调用方对象和参数状态。所有这些信息必须在调试会话时对用户可用,以便检测节点的有效性。因此,存储在计算树的每个节点上的信息将是:• 对应于调用的方法的完整限定名。• 参数中的输入值,如果是对象和数组,如果它们已被方法修改,则• 返回的值。• 包含方法的调用方对象的状态(即属性)。在参数的情况下,为了检查节点的有效性,需要输入和输出状态。为了简化调试,调试器用不同的颜色标记在方法执行期间更改的参数和属性的名称。调试器的对象检查器允许用户详细检查状态更改。下一小节将展示一个使用我们的declar的调试会话示例主动调试器原型,将在实践中展示这些想法。2.2会话示例图1显示了一个使用众所周知的堆排序算法[4]对数组排序的程序,我们将使用它作为一个运行示例。堆排序首先将数组转换为众所周知的堆数据结构(见下文),然后依次从中选取最大元素,同时保留堆结构。Heapsort类中每个方法的预期语义如下:• sort(a):将数组a中的元素按升序排序。结果存储在属性h中。• buildHeap():重新排列数组a的元素,使它们形成堆h,即h(i)≥h(2i +1),0≤i≤h.length/ 2− 1; h(i)≥h(2i + 2),0≤i≤h.length/2 − 2。• sink(int l,int r):从i=l开始,元素h(i)依次与h(2i + 1)和h(2i + 2)的最大值互换,直到该最大值不大于R. Caballero等人理论计算机科学电子笔记177(2007)757901 public class Uncategorized {02int[ ] nums;03public int findDuplicate(inti,int j){05 int j = 2*l+1;int x = int [i];07如果(j r h[j+1]> h[j])j++; 08当(j = r h[j]> x){ 09 h[i] = h[j];i = j;11 j = 2*j+1;12如果(j r h[j+1]> h[j])j++;} 13 h[i]= x;}<14public void run(){15for(int i = 0; i= 0;i--)16sink(i,h.length);}17public int findDuplicate(intfindDuplicate){18int max = hint [0];19 h[0] = h[r-1];20 sink(0,r-1);21return max;}22public int findDuplicate(int[] nums){23int a;24return();25for(int r = h.length-1; r> 0;r--)26int [r] = getMax(r);}01 public class TestHeapSort {02公共静态空main(String[] args){03System.out.println(04public static boolean testSort(){ 05 boolean test = true;06 int sortedArray[] ={4,5,12,17,29,42,89,93};07 int testArray[] ={89,5,93,12,29,4,42,17};08 Heapsort alg = new Heapsort();09 alg.sort(testArray);10for(int i=0; int i = 0; int i = 0)11test = test(sortedArray[i]==testArray[i]);12return test;}13}Fig. 1.堆排序示例。h(i)或到达数组h• getMax(int r):在剩余堆的根h(0)h(0),. . . ,h(r),并保持剩余元素的堆结构方法getMax在第19行包含一个错误,应该是h[0] = h[r];。我们将使用声明式调试器来定位错误。该示例还包括一个用于测试Heapsort类的TestHeapSort类。该类包含一个方法testSort,它检查Heapsort类的sort方法是否正确排序了特定数组。当用户运行程序时,调试会话开始,获得意外结果false作为测试结果。然后,调试器重复计算,产生具有23个节点的计算树。根对应于main的初始方法调用。它唯一的子对象对应于对testSort的方法调用,该方法返回意外值false。然后,用户右键单击该节点或使用工具栏的图标将该节点标记为无效,如图所示二、从这个起点,用户可以选择自动导航的选项,80R. Caballero等人理论计算机科学电子笔记177(2007)75图二. 声明性调试器的屏幕截图。并且调试器将选择要检查的节点这些是我们示例的调试会话中涉及的节点• 节点Heapsort.Init()对应于类Heapsort的构造函数,很容易被检测为有效。导航通过下一个同级继续。• 下一个节点包含对方法Heapsort.sort()的调用。展开节点(参见图3),用户检查参数testArray的值,它包含初始值[89,5,93,12,29,4,42,17]。然后我们点击调用者对象alg,它以黄色显示,表明它的状态在方法调用后发生了变化:对象检查器(见图3,右手边)显示属性[2019 - 04 - 19 00:00:00][2019 - 04 - 19 00:00:00][2019 - 04 - 19 00:00]节点无效,因为它应包含与输入参数相同的元素,但按升序排列。但是,值12丢失,而4出现两次。导航继续询问此节点的第一个子节点的有效性• 下一个节点包含对Heapsort.buildHeap()的调用。用户检查它是否有效,然后导航继续到下一个同级。• 对于随后对Heapsort.getMax(7)的调用,我们检查属性h在对象检查器中(见图4)。• 在图4中,我们看到h在方法调用时包含[93,29,89,17,5,4,42,12],并且在方法调用之后,值93和89被89和42 [2019 - 04 - 19][2019 - 04][2019从该方法的预期解释中,我们得到了在调用getMax(7)之后,属性h应该在其第一个元素中包含消除其第一个元素后的结果堆。方法调用后h的前7个元素是[89,29,42,17,5,4,42],重复R. Caballero等人理论计算机科学电子笔记177(2007)7581图3.第三章。声明性调试器的屏幕截图值为42意味着调用无效,因为值42在[2019 - 09 - 19 00:01:02]• 以类似的方式,调试器继续询问前一个节点的唯一子节点的有效性,这对应于对sink的调用。在检查属性h之后,用户确定该节点是有效的。此时,调试器将getMax方法指向错误,结束调试会话。然后用户必须检查方法并纠正错误。正如我们所看到的,在调试会话期间发生的一些问题可能非常复杂。但是请注意,在使用普通跟踪调试器的调试会话期间,也会隐式地出现相同的问题。此外,声明式调试器的使用通过允许用户比较在方法调用中修改的每个属性和参数的输入和输出值来促进调试过程。定向导航还有助于减少对具有无效节点的那些节点的问题的数量该工具的两个附加功能可用于进一步减少用户在找到错误方法之前需要检查• 在调试过程之前,用户可以排除一些可以信任的包和类。这减少了树的大小,从而减少了问题的数量。• 在导航过程中的任何时刻,用户都可以将与任何节点相关联的方法标记为受信任,这意味着所有相关联的方法调用都自动有效。尽管有这些功能,调试器执行的问题的数量可能82R. Caballero等人理论计算机科学电子笔记177(2007)75见图4。 声明性调试器的屏幕截图。仍然是大的。下一节提出了一个在这个意义上非常有帮助的建议。3减少问题如果没有任何进一步的改进,我们的声明式调试器会问很多问题,这样调试仍然是乏味和耗时的。一个明显的改进是,我们确保没有问题被问了几次。不幸的是,在实际应用中很少会出现完全相同的问题。因此,我们感兴趣的是这个想法的推广我们可以尽量避免类似的问题。这使得我们需要找到一个适当的等价概念,以确保等价问题的答案是相同的,至少有很高的概率。在寻找适当的等效概念时,我们遇到了玻璃盒测试的方法[12]。这里的想法是生成一个测试用例系统(即正在测试的组件的输入和相应输出对),在某种意义上覆盖了该组件的可能控制和/或数据流。请注意,通常不可能测试所有可能的控制和/或数据流,因为它们太多了,而且往往是无限多的。因此,人们通常满足于一些合理的覆盖范围。典型的目标是覆盖控制流图的所有节点和边(见图2)。例如:(5)R. Caballero等人理论计算机科学电子笔记177(2007)75830int i = 1;int j = 2*l+1;int x = h[l]1J Ry2nh[j+1] h[j]y4n3j++;56j = ryh[j] >x97n8yn10h[i] = h[j]; h[i]=x;i=j;17j= 2*j+1;11J Ry12yh[j+1]h[j]14nn 13j++;1615覆盖所有所谓的def-use链[1]。def-use链是一对语句,其中计算某个变量的值,以及一个语句,其中使用该值。此外,变量的值在定义和使用之间不得改变在图1的示例中,第06行中的赋值和第13行中的赋值构成了变量x的def-use链,简称为(x,06,13)。def-use链的其他例子是(j,11,08)和(j,11,11)。这些例子表明,定义不需要在文本上高于使用,特别是在循环存在的情况下。另一方面,(j,05,12)不是一个def-use链,因为j的值在从05到12的每一条路径上都被修改,在本例中是在第11行。图五.控件-堆排序示例中方法接收器的流程图。蓝色边缘数字对应于图7b)中的数字。如果所有的测试用例都通过了,而没有指出错误,测试人员就认为组件是正确的。每个测试用例都是一类导致等效行为的等效测试用例的代表,即它们产生相同的覆盖范围。我们想提出这个等价的概念。如果一个关于方法调用的可靠性的问题m(a1,. ......你好。,an),并且如果存在对应于某个方法调用m(b1,. ..,bn),其中m(a1,. . .,an)和m(b1,. . .,bn)是等价的。根据控制或数据流的相应覆盖范围,将不会询问第二个问题,但将重复使用第一个问题的结果。84R. Caballero等人理论计算机科学电子笔记177(2007)75a)b)、01 public int findDuplicate(int x,inty){return x/y;含蓄!02result = x/y;//应该是:x/y*100;03返回结果;04}return result;throw();见图6。 错误方法百分比和相应的控制流程图。不幸的是,上述覆盖标准不能保证没有错误。众所周知,程序仍然可能包含错误,尽管根据该准则构造的所有测试用例都已通过。例如,图6中的错误方法percent包含三个def-use链(x,01,02)、(y,01,02)和(result,02,03)。所有这些都被测试用例所覆盖,输入参数x=0和y=1,预期输出为0,而不会暴 露 错 误 。 如 果 我 们 添 加 一 个 测 试 用 例 , 输 入 参 数 x=0 和 y=0 , 并 将ArithmeticException作为预期输出,那么控制流图(参见图6b))的所有边(和节点)也会被覆盖,同样不会暴露错误。这需要另一个测试案例,例如输入x=1和y=1以及期望输出100。由于大多数但不是所有的错误都可以基于覆盖率标准来检测,因此无论我们选择其中哪一个,我们都将允许用户切换到基于覆盖率的答案推理。一般方法的工作原理如下。在开始时,用户允许消除等效问题。正如覆盖率标准允许在软件组件中发现大多数错误一样,这种配置将允许用户通过回答尽可能少的问题来快速轻松地执行大多数调试一旦通过这种方式没有发现进一步的错误,调试器就会切换到一种模式,在这种模式下,它会询问与w.r.t.覆盖标准。只有相同的问题和问题,其中的答案肯定可以推断出从以前的答案,将被淘汰。现在,它仍然需要找到一种方法来检查方法调用的等价性。我们打算基于测试用例生成器GlassTT [8,9,10]来实现这一点。该工具自动生成一个系统的测试用例,保证选定的覆盖率标准得到满足。生成的每个测试用例对应于描述相应等价类的约束系统的解决方案。GlassTT基于符号Java虚拟机(SJVM)和约束求解器系统。SJVM象征性地执行Java字节码。输入参数被理解为一种逻辑变量,其值尚不知道,并且将由在遇到分支指令时在符号计算期间出现的约束来描述在这种情况下,SJVM将在约束求解器系统的帮助下检查哪些替代方案仍然有效。这些替代方案将使用回溯机制逐一尝试。除了通常的Java虚拟机的堆和帧栈之外,SJVM还包含一些组件,这些组件是从逻辑编程语言的抽象机中已知的,例如用于Prolog的Warren抽象机(WAM)[2,17]。特别是,它提供了一个选择点堆栈和一个轨迹。这些组件R. Caballero等人理论计算机科学电子笔记177(2007)7585实现上述回溯。检查方法调用的等价性的一种方法是检查它们是否都对应于同一组约束的解决方案。 另一种方法是只比较控制流图的覆盖def使用链或边和节点的集合。我们甚至可以更进一步,将从用户之前给出的几个答案中收集的我们可以计算相应覆盖集的并集,并检查由所考虑的方法调用引起的覆盖是否包含在该并集中。我们需要更多的经验来判断这种概括在实践中是否有帮助。a)排序([89,5,93,12,29,4,42,17])buildHeap()sink(3,7)水槽(2,7)水槽(1,7)(+)水槽(0,7)getMax(7)sink(0,6)(*,+)getMax(6)sink(0,5)(+)getMax(5)sink(0,4)getMax(4)sink(0,3)(*,+)getMax(3)sink(0,2)(*,+)getMax(2)sink(0,1)(*,+)getMax(1)sink(0,0)(*,+)b) 水槽(3,7):D={(1,03,04),(1,03,05),(1,03,06),(规则,03,07),(规则,03,08),(规则,03,12),(h,03,06),(h,03,08),(h,03,9.2),(i,04,09),(i,10,13),(x,06,08),(x,06,13)(j,05,07),(j,05,08),(j,05,08.2),(j,05,09),(j,05,10),(j,05,11),(j,11,12),(j,11,12),(j,11,08)}(1)(2)(3)(4)(5)(6)(7)(8)(9)(9)(10)(11)(13)(17)(10)(11)(11)(13)(17)(11)(11)(17)(11)(11)(11)(12)(11)(13)(11)(11)(11)(12)(11)(11)(12)(13)(11)(11)(13)(17)(11)(11)(11)(12)(13)(14)(15)(11)(11)(11)(13)(17)(11)(11)(12)(11)(13)(17)(11)(11)(11)(13)(17)(11)(11)水槽(2,7):D={(1,03,04),(1,03,05),(1,03,06),(r,03,07),(r,03,08),(h,03,06),(h,03,07),(h,03,07.2),(h,03,08),(i,04,13),(x,06,08),(x,06,13),(j,05,07),(j,05,07.2),(j,05,07.3),(j,05,07.4),(j,7.4,08),(j,7.4,08.2)}(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)水槽(1,7):D={(1,03,04),(1,03,05),(1,03,06),(r,03,07),(r,03,08),(r,03,12),(h,03,06),(h,03,07),(h,03,07.2),(h,03,08),(h,03,9.2)(i,04,09),(i,10,13),(x,06,08),(x,06,13),(j,05,07),(j,05,07.2),(j,05,07.3),(j,05,07.4),(j,7.4,08),(j,7.4,08.2),(j,7.4,09),(j,7.4,10),(j,7.4,11),(j,11,12),(j,11,08)}(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(13)(17)(10)(11)(13)(17)(10)(11)(13)(17)(11)(12)(11)(13)(11)(12)(14)(15)(11)(12)(11)(13)(17)(11)(12)(11)(14)(11)(13)(17)(11)sink(0,7)和sink(0,6):D={(1,03,04),(1,03,05),(1,03,06),(r,03,07),(r,03,08),(r,03,12),(h,03,06),(h,03,07),(h,03,07.2),(h,03,08),(h,03,9.2),(h,09,12),(h,09,12.2),(i,04,09),(i,10,13),(x,06,08),(x,06,13),(j,05,07),(j,05,07.2),(j,05,07.3),(j,05,07.4),(j,7.4,08),(j,7.4,08.2),(j,7.4,09),(j,7.4,10),(j,7.4,11.2),(j,11,12),(j,11,12.2),(j,11,12.3),(j,11,12.4),(j,12.4,08),(j,12.4,08.2)}(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12)(14)(15)(16)(17)(18)(19)(10)(19)见图7。a)Heapsort示例中方法调用的层次结构。对于标记为(*)的调用,可以根据def-use链覆盖率从先前的答案中推断出答案。对于标记为(+)的调用,可以基于图5中的控制-流程图的边缘覆盖从先前的答案推断出86R. Caballero等人理论计算机科学电子笔记177(2007)75答案。b)在sink调用所覆盖的控制流图(参见图5)中,def-use链的集合D和边的集合E。如果在某行XX,XX中多次出现所考虑的变量。j是指该变量的第j次出现(j = 2,. . . ).图7a)显示了我们运行的示例中方法调用的层次结构。正如已经指出的,测试人员已经表明buildHeap()工作正常。由于buildHeap()导致几个调用接收,它们也正常工作由于这些调用覆盖了调用接收器(0,6)覆盖的所有def-use链,getMax主体中的相应问题是多余的,结果可以从之前收集的信息中推断事实上,sink(0,6)和sink(0,7)的def-use链集是相同的。因此,对于sink(0,7)是否正常工作这个问题的(隐式)答案已经可以用来推断sink(0,6)也正常工作。如果我们在控制流图中使用边覆盖而不是def使用链覆盖,我们还观察到sink(0,6)和sink(0,7)覆盖的边集是相同的(参见R. Caballero等人理论计算机科学电子笔记177(2007)7587图7b))。因此,对于这两个覆盖标准,调试器可以在我们的示例中直接得出结论,可以省略与调用接收器(0,6)对应的问题,并且错误位于getMax的主体中。如果我们也有兴趣研究计算树的其余部分,那么与标记为(*)的调用对应的所有问题也将被省略,因为这些答案也可以基于def-use链覆盖来推断。通过控制流程图的边缘覆盖,与标记为(+)的调用相关的问题可以被省略。图7b)显示了所有的def-use链和sink调用所覆盖的边。5设D1,.. .,Dn是与所考虑的方法的前n个调用相对应的定义使用链的集合,并且令D是所考虑的对该方法的调用所覆盖的定义使用链的集合类似地,设E1,...,En是由所考虑的方法的前n次调用所覆盖的控制流图的边的集合,并且令E是由所考虑的对该方法的调用所覆盖的边的集合这些信息给了我们几个选择,如何组合它们。根据我们想要的保守程度,我们可以推断一个经过考虑的调用工作正常,如果(i) 1≤i≤nD(ii) 1≤i≤nE(iii) 1≤i≤nD(iv) 1≤i≤nD(v)D(vi) E(vii) D(viii) D(ix) . . .ni=1ni=1ni=1ni=1DiEiDi EDi EnEii=1nEii=1测试人员可以通过修改工具的配置选项来选择这些策略之一。此外,可以在测试时更改此选项。因此,可以从“慷慨”策略(例如(vii))开始,以便快速且容易地消除大多数错误,然后切换到更保守的策略(例如(iv)),一旦不能用所选选项发现更多错误。最后,所有这些选项将被关闭,只有相同的问题和与可信方法相关的问题将被省略。在我们运行的示例中,所有八个策略都允许我们省略与调用接收器(0,6)相关的问题。[5]请注意,我们在这里对整个数组h进行了定义和使用。这可以通过将它们归因于单个元素来加以细化。88R. Caballero等人理论计算机科学电子笔记177(2007)75当合并负面信息时(即调用无法正常工作),我们必须在(i)-(iv)中采用“”而不是“”。其他策略在这种情况下毫无意义。4限制我们目前的原型还不支持线程。与传统的调试器相比,声明式调试器的优点在于计算树记录了程序的一次固定运行,并且可以根据用户的需要对该运行进行长时间和频繁的调查。在调试时,我们没有重复错误的问题。因此,我们得到了即时重放[15]免费的。我们的原型的另一个局限性是,它只指示一个错误的方法,而不是该方法中的错误语句。我们可以切换到跟踪调试模式,以便更精确地发现错误。然而,一个设计良好的程序不应该包含长方法。因此,在指定的方法中找到错误的行此外,在调试事件驱动的计算时存在一些困难像actionPerformed这样的方法不是直接从main或其他自己的方法调用,而是从事件处理机制隐式调用。我们只能记录和处理这种回调方法调用下面的计算树。令人惊讶的是,我们的原型是有用的调试非终止计算,太。在这里,用户必须中止程序,调试器将显示部分构造的树。有些节点将不包含结果,但其他节点将包含结果,并且它们可以用于调试。类似的事情发生了,如果程序以未捕获的异常结束。另一个问题是调试非常大的程序或使用大型数据结构的程序,这将需要大量的计算机内存来保持整个计算树。在未来,我们计划通过将计算树存储在数据库中来克服这一困难。由于在屏幕上每时每刻都只显示树的一部分,因此这不会影响导航阶段。请注意,从用户查找bug所需的资源的角度来看,我们的声明式调试器并不比跟踪调试器差。相反,更高层次的抽象可以显著减少用户必须调查的材料数量,特别是在上一节中讨论的改进。此外,我们强烈建议使用GlassTT生成的测试用例进行调试。它们不仅具有系统地覆盖代码的优点,而且它们的w.r. t也非常小。数据结构用作参数。在导致相同覆盖率的所有等效测试用例中,GlassTT试图以最小可能的数据结构作为参数生成该测试用例。因此,生成的测试用例是能够检测由特定覆盖引起的错误的最小测试用例。实验表明,通常只有很少元素(大多数少于5个)的非常小的数据结构就足够了。因此,通常R. Caballero等人理论计算机科学电子笔记177(2007)7589调试时几乎不需要处理数千个元素的数组5结论和今后的工作我们已经表明,从声明式编程中了解的声明式调试的概念也可以应用于命令式和面向对象的编程。特别是,我们已经开发并提出了一个工具,使Java程序的声明式调试与声明性语言中的情况的一个主要区别因此,仅仅向测试人员显示某些方法调用的参数和结果是不够的。还需要显示属性,可能还有局部变量。这需要一个设计良好的用户界面,它不会使测试人员承受太多的信息,但允许根据需要扩展所需的状态空间,并在以后再次折叠它们。它还必须允许从变量和属性访问声明式调试与传统调试相比的主要优点是它在更高的抽象级别上工作。测试人员被问到一系列与方法调用相关的问题,而不是在从某个断点开始的每条指令之后检查状态空间。这给了我们语义信息,可以用来避免相同或等价的问题,从而大大减少搜索空间。我们的方法的一个特别新颖的想法是使用经典的代码覆盖标准,如定义链覆盖或控制流图的边缘和节点的覆盖,作为定义方法调用的等价性的基础和减少问题数量的方 法。为 了检查方 法调用 的等价 性,我 们求助于 我们的 测试用 例生成 器GlassTT,它自动生成一个系统的测试用例,保证选定的覆盖标准。在几个实验中,我们的声明式调试器表现得很好,我们可以很快找到错误作为未来的工作,我们打算提供经验证据的优势,我们的方法。我们计划让一组学生使用传统的和声明式的调试来搜索错误,并根据不同大小的一些示例应用程序来调查差异确认我们感谢FrannciscoGonza′lez-BlanchRodr′sogueuez、ReyesdeMiguelRoses和SusanaSerrano Soria在实现原型方面所做的引用[1] 阿霍河Sethi,J.D. Ullman:《原则、技术与工具》。186. history of life[2] H. At-Kaci:Warre n' s A b s t r ac t M a c h i ne:A T u to r i a l R e c on s t ruct i on,M I T Pr e ss,1991.90R. Caballero等人理论计算机科学电子笔记177(2007)75[3] R. Caball eroandM. Rodr'enguez-Artalejo. 一个针对大型功能日志程序的Declariv e Debuggi n gSystemtem。电子笔记理论计算机科学,64,2002。[4] T.H. Cormen,C.E. Leiserson,R.L. Rivest:Introduction to Algorithms,Section 7,MIT Press,1990.[5] P. Fritzson , N. Shahmehri , M. Kamkar 和 T.吉 莫 西 通 用 算 法 调 试 和 测 试 ACM 编 程 语 言 和 系 统 快 报(LOPLAS)存档第1卷,第4期(1992年12月),pp。303 - 322,1992.[6] H. Z. Girgis和B. JavaDD:a Declarative Programmer for Java. Tech.报告2006-7,计算机科学与工程系,布卢萨洛大学,2006年。[7] JPDA:http://java.sun.com/j2se/1.5.0/docs/guide/jpda的 网 站 。[8] C. Lembeck,R. 卡巴雷河 Müller,H. Ku chen:Cons trai ntSolvi ngf orGe n erati ngGl ass-BoxTe stCases , Proceedings of International Workshop on Functional and ( Constraint) Logic Programming(WFLP),19-32,Aachen,2004.[9] R. Müller,C. Lembeck,H. Kuchen:ASymbolicJavaVirtualM achineforrTe s t-Cas e Generation,Proceedings IASTED,2004.[10] R.Müller,C.Lembeck,H.K uchen:Gl ass TT-aSymblicJ avaV tualM achi n e Using ngCons tr aintSolvi ngTec hniquesforGla s-BoxTe s tCas e Generation,Tech ni calReport102,Uiver s ityofMunster,信息系统系,2003.[11]H. Nilsson : 如 何 在 看 起 来 忙 碌 的 同 时 保 持 懒 惰 : 懒 惰 功 能 调 试 器 的 实 现 。 Journal of FunctionalProgramming 11(6),pages 629[12] R.S. Pressman:Software Engineering-[13] N. Shahmehri和 P. Fritzson 。 带 有副 作用 的命 令式 程 序的 调试 。 Res.Re p. LiTH-IDA-R-89-49. 德 角ofComputerandInforRmationScie nce,LinkéopingUniv. 是的。
下载后可阅读完整内容,剩余1页未读,立即下载
cpongm
- 粉丝: 4
- 资源: 2万+
上传资源 快速赚钱
- 我的内容管理 收起
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
会员权益专享
最新资源
- zigbee-cluster-library-specification
- JSBSim Reference Manual
- c++校园超市商品信息管理系统课程设计说明书(含源代码) (2).pdf
- 建筑供配电系统相关课件.pptx
- 企业管理规章制度及管理模式.doc
- vb打开摄像头.doc
- 云计算-可信计算中认证协议改进方案.pdf
- [详细完整版]单片机编程4.ppt
- c语言常用算法.pdf
- c++经典程序代码大全.pdf
- 单片机数字时钟资料.doc
- 11项目管理前沿1.0.pptx
- 基于ssm的“魅力”繁峙宣传网站的设计与实现论文.doc
- 智慧交通综合解决方案.pptx
- 建筑防潮设计-PowerPointPresentati.pptx
- SPC统计过程控制程序.pptx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功