第28卷 第4期 VO1.28 NO.4 计算机工程与设计 Computer Engineering and Design 2007年2月 Feb.2007 未初始化变量的一种静态测试方法 赵鹏宇, 万琳, 宫云战 (装甲兵工程学院信息工程系,北京100072) 摘要:软件测试系统的研制是软件测试领域的一个研究热点。未初始化变量是c/C抖程序中的常见故障,该类故障极 导 致计算结果错误或系统崩溃 针对c/C抖语言中常见未初始化变量故障进行了分析研究,并从面向具体故障的测试思想出 发,建立了c/C++语言中未初始化变量的故障模型,结合静态测试的特点,给出了一种静态查找此类故障的方法。该方法已 实现,并已应用于面向故障的软件测试系统中。 关键词:软件测试;静态测试;未初化变量;语法树;控制流图 中图法分类号:TP302.8 文献标识码:A 文章编号:1000-7024(2007)04.0751-4 0Static detecting method for uninitialized variable ZHAO Peng—yu, WAN Lin, GONG Yun—zhan (Department of Information Engineering,Armored forces Institute,Beijing 1 00072,China) Abstract:Uninitialized Variable iS a common kind oferror in programs written in C,C++.which often causcs system collapse.Firstly, the classical C/C++uninitialized variable errors is analysed.a defectmodel ofuninitialized variable OfC/C++based on the defect-oriented testing strategy is established,then a detecting me ̄od of uninitialized variable errors combming the advantage of static analysis is de- scribed.This theory is implemented in a defect-oriented testing system. Key words:software testing;static testing;uninitialized variable;syntax tree;controllng istream raph gO引 言 软件测试可以分为静态测试方法和动态方法。软件测试 的目的在于发现错误,进一步可以针对某一种或者某几种错 误进行专门的测试,这种测试叫做面向具体错误类型的测试。 C/C抖对变量的声明、初始化和引用都非常灵活,给程序员写 程序带来极大的方便和效率。但是,由于程序员的理解偏差 和粗心,在编写程序时,程序员往往对没有初始化的变量进行 引用,从而导致程序的输出结果错误或死机。虽然有些工具能 够检测出简单的未初始的变量的错误,但是对于较复杂的变量 称。它的主要特点是不利用计算机运行被测试的程序,而是 采用其它手段达到检测的目的。有人认为静态分析只是动态 分析的预处理工作,认为静态分析并不是要找出程序中的错 误,因为编译系统已经能够做到这一点了。实际上,这种看法 是片面的,尽管编译系统也能发现某些程序错误,但这远非软 件中存在的大部错误。静态分析的查错功能是编译程序不能 代替的。 1.2未初始化变量错误 未初始化变量顾名思义就是变量在声明以后,没有对其 初始化赋值就进行引用,导致了程序出错或死机。 例如: l2 l char readline(char*bu0 f 122 123 charc; char savebuf=buf; 类型(结构体变量、指针变量、数组等),这些工具的检测结果却 不尽人意。另外这些工具也检测不出程序中每条执行路径上 的未初始化变量的错误。解决上述问题恰恰是静态软件测试 方法所擅长的。然而静态方法由于不实际执行被测程序所以 在找到一个潜在的错误后还需要人工确认是否是真正的错误。 124 125 while(c!=EOF&&(c=getcharO)!=’、Il’) bu 斗=c: 1基本概念 1.1静态分析 静态分析是对被测程序进行特征分析的一些方法的总 收稿日期:2006-01—16 E-mail:zhaopengyu006@163.Gore 126 buf= \0’: 127 128 if(c—EOF&&but"一savebuf) ieturn NULL; 基金项目:总装备部十五预研基金项目(41315050107)。 作者简介:赵鹏宇(1981一),男,河北唐山人,硕士研究生,研究方向为软件工程、软件测试等; 万琳(1974一),女,山西太原人,博士,研 究方向为软件工程、软件测试等; 宫云战(1961--),男,山东威海人,博士,教授,博士生导师,研究方向为软件工程、软件测试、集成电路 测试等。 一75l一 维普资讯 http://www.cqvip.com
129 else 130 return savebuf; 利用LEX和YACC来进行。 1.4符号表 变量名字分析与变量名字的使用和变量声明有着密切的 关系。为了得到很好名字分析的效果,在生成语法树的同时 生成了一个符号表。这个符号表为每个被声明的变量建立一 个表项,描述了变量的作用域和它是如何被嵌套声明的。变 量名字的分析结果就是为每个变量在符号表中生成一个表项。 131} 在上面的程序中在变量C被赋为下一值前要判断变量C 的值是否为EOF。由于变量C在122行被声明,而在124行第 一次循环前没有被赋初值,就产生了未初始化变量的错误。 再如: 100 intb,c; 101 scanf(”%d.-’b); 102 if(b>0) 103 c=25; 104 c=c+b: 在上述程序第100行声明了两个变量b和c,在第101行变 量b被初始化。在程序的104行,变量c要被变量c和变量b的 和赋值。但是如果变量b的值小于或等于0,则第103行将不 会被执行到,在140行仍然会出现未初始化变量的错误。While, dowhile,for等语句同样会出现上述情况。而程序员在编写出 上述程序时,编译器不会报出任何错误或警告。 C,C斗_卜语言提供的变量类型非常丰富。基本类型有整型 变量、字符型变量、实型变量、枚举型变量,指针类型变量;构 造类型变量有数组类型变量、结构体变量、共用体类型变量等。 程序员在编写程序时由于其粗心或理解偏差,往往在声 明变量后不加以初始化就对其进行引用或者程序在真正执行 时,从程序的入口到程序的出口可以有多条路径,有时变量只 在某条路径上被初始化,而在其它路径上,程序员却忽略了对 变量的初始化,而在随后的变量引用时导致了程序的出错。 1.3语法树 语法分析主要是将输入字符串识别为单词符号流,这里 主要是找出变量声明语句,并相应的分离出各种类型的变量。 按照标准的C斗_卜语法规则,对源程序作进一步分析,比如什么 是变量定义,什么是赋值语句,什么是函数。语法分析的结果 是生成语法树,它被保存在内存中,是源代码的内部表示。其 它模块可以方便地访问语法树来完成各种各样的任务如:源 代码分析、C,C斗_卜源代码到其它源代码的翻译等。源代码的任 何一条语句在语法树上都有一个节点与其相对应,例如声 明语句: static unsigned int a【5】,b---l; 这条声明语句在语法树中对应的结点如图1所示。 构造程序完整的语法树和编译系统前端工作相同,可以 图1 声明语句在语法树上的结点结构 一752一 例如程序: class C{ intflintx1){ int x2.x3; {Int x3,x4;) {int x2,x4;) ) nitg(nitx1): ); 这段程序的符号表的结构如图2所示。 图2类C符号表 构造程序完整的符号表和编译系统前端工作相同,也可 以利用LEX和YACC来进行。 1.5程序控制流图 程序的控制流图是对程序控制结构的图形表示,它是一 种有向图。控制流图中的节点表示程序的语句,边表示控制 流。另外对于每个函数的控制流它还包含一个惟一的入口结 点和惟一的出口节点。在每个函数调用的地方存在一个调用 节点和返回节点,如图3所示。 Voidfunction(intX,nity) { if(x>y) 图3程序控制流 维普资讯 http://www.cqvip.com
printf(“%d,’,x); else 分析,查出其中的错误是我们所关心的。 在程序的执行中所使用的集合有: ble{):用来记录被测程序中的出现的所有变量。 Vex{}:控制流图的所有结点集合。 DelNode{):用来记录程序中出现的每个变量在程序控制 流图中被声明节点号。 IniNode{):用来记录程序中出现的每个变量在程序控制 流图中的被初始化的所有结点号。 UsedNode{):用来记录程序中出现的每个变量在程序控 TempNode{):用来记录经过CutNode操作的被删除的结 printf(“%d,’,y); ) 2以语法树和控制流图为基础的未初始化变量 错误分析 2.1系统设计 构建错误类型模型查找测试的核心是对源程序进行词法 分析和语法分析,生成被测程序的语法树和控制流图。系统 设计如图4所示。 一一一 一一一 制流图中被使用到的结点号。 源程序 预编译 生成数据库 文件 至 图4故障检查流程 (1)预编译:由于源程序中存在宏定义、文件包含和条件编 译等预处理命令,因此在进行词法分析前必须进行宏展开等 预编译工作。 (2)词法分析:将预编译阶段产生的中间代码分解成单独 的词的表示,形成各种符号表、类型表、关键字表、常数表、运 算符表和分界符表。符号表中包含有利于错误查找的一些相 关信息,如:位置、行号、错误类型,这些信息对于错误的查找 和定位都有十分重要的作用。 (3)语法分析:这一步主要是将输入字符串识别为单词符 号流,这里主要是找出变量声明语句,并相应的分离出各种类 型的变量。按照标准的C++语法规则,对源程序作进一步分 析,比如什么是变量定义,什么是赋值语句,什么是函数。语 法分析的结果是生成语法树,每一个语法规则对应一个相应 的处理函数,并作为语法树的一个结点挂在语法树上,提供对 外的接口。 (4)生成控制流图:以语法树为基础,根据程序的控制结 构,用递归的算法在遍历语法树时生成程序的控制流图。控 制流图中的每个节点表示程序的一条语句,与语法树上相应 的语句结点相对应。另外对每个函数的控制流图它还包含一 个惟一入口结点和惟一的出口结点。在函数的调用的地方存 在一个调用节点和一个返回结点。 (5)以第3步和第4步生成的语法树和控制流图为基础, 根据算法分析程序控制流图和语法树,在这过程中对变量进 行分析,找出未始化的变量。 (6)如果找到相匹配的错误,则将错误信息记录到数据库文 件中,最后得到数据库文件。数据库文件是得到的最终的结果, 其中包括经过测试得到的一些相关信息,如未初始化变量名、 该变量被定义的行号、该变量被使用的行号、错误类型等。最 终由数据库文件生成错误信息报表,将错误信息反馈给用户。 2.2算法设计 错误的查找是系统设计的目标,如何对源代码进行静态 点号和该结点的所有入边和出边。 所用到的操作有: Add(S,Elem):将元素Elem加入到集合S。 Kill(S,Elem):将元素Elem从集合S删除。 CutNode(G,node):在程序控制流图G中将结点node删除, 并将该结点的所有入边和出边一同删除。 RefreshGraph(G):把经过CutNode操作的程序控制流图G 还原为进行CutNode前的状态。 算法描述: (1)遍历被测程序语法树,收集被测程序中出现的所有变 量的信息,生成变量表VarTable{),生成该程序的控制流图G: ( E),V为图中结点集,E为有向边集;e T(e),H(e))表示相邻 结点对,其中边e离开T(e)结点,进入H(e)结点。 (2)广度优先遍历程序的控制流图G,在遍历过程中如果 遇到变量vat的声明结点,则将该变量的声明结点号加入该变 量的声明结点集合中,即执行Add(DelNode,v)操作;如果遇到 变量vat的初始化结点,则将该变量的初始化节点号加入该变 量的初始化结点集合中,即执行Add(IniNode,v)操作;如果遇 到变量var被使用的结点,则将该变量的被使用节点号加入该 变量的被使用结点集合中,即执行Add(UsedNode,v)操作。 (3)顺次扫描被测程序的变量表,对该表中的每个变量进 行如下操作: 如果该变量的初始化集合InjN0de非空,则遍历被测程序 的控制流图,在被测程序的控制流图中删除该结点及其连接 边e,e满足aXe ̄n或H(e)==n;得G Ⅳ ’;即对该变量IniNode 集合中的所有结点进行CutNode(G,vex)操作。 如果该变量的UsedNode集合非空,则顺次取出该变量的 使用结点,在被测程序的控流图中寻找是否存在一条该变量 的声明节点到该变量的使用节点的通路。如果存在,则检测 出了未初始化变量错误,将这条错误记录写入到数据库中。否 则,goto(4)。 (4)检查变量表岫ble,如果变量表VarTable中尚有未被 扫描过的变量,则恢复被测程序的控制流图G,即执行Refresh. Graph(G),goto(3);否则退出测试程序。 2.3算法分析 (1)当变量作为参数时,有可能在函数内初始化,再传递出 来,对于该情况,全部报出IP,再判断是否误报; (2)条件内初始化(if,while等):如果条件始终成立(恒真, 或if,else分支都有初始化),则不报,否则全部报出Il',再判定 ・——753-—— 维普资讯 http://www.cqvip.com
是否误报; (3)case结构中的初始化(包含if嵌套结构):确定是否有 default分支,且在该分支内有初始化,有则不报,否则全部报 出IP,再判断是否误报; (4)静态或全局变量定为误报。 项目 编号 l 2 3 4 表2测试结果比较 本文所述方法 Reasoning工具 IP总数 故障总数 准确率 IP总数 故障总数 准确率 73 l15 113 4lO 12 56 33 l3O l6.4% 48.6% 24.8% 31.7% lO3 l12 165 35l 22 48 32 66 8.4% 48.2% 17.9% l8.4% 3实验结果和对比分析 我们以不同大小的程序模块来检测我们开发的未初始化 合计 7l1 23l 32.4% 73l l68 22.9% 变量的静态软件测试系统。具体的作法是:首先运用软件测 试工具对软件进行测试,标记出测试工具认为可能出现的错 误点来,称之为检测点IP,经检测后提供一个中间文件给测试 人员,由测试人员再对照这些IP,复查源代码,最终确定这些 IP点是否是一个Defect。表l给出了对些项目进行测试得出 的IP数和经人工确认后的对比结果。 保证找出程序中所有的此类错误,但是找到的确实是实实在在 的错误,仅这一点就足以说明这种分析方法的有效性。当然, 该工具还有很多需要扩展和改进的地方。如:引入简单的符号 执行处理多个判断条件组合的问题等。在以后的工作中还要 考虑空指针引用、数组越界、内存泄漏等错误类型的分析。 参考文献: 表l IP数和确认以后结果对比 File Size/M 4_38 l24 [1】Bush W R,Pincus J D,SielaffD J.A static analyzer for ifnding dynamic programming errors-【R]Software-Practicend aExpe— rience,2000,30(7):775-802. 3 5 Inspection Points 12 lO I ̄fccts [2】 宫云战.一种面向故障的软件测试新方法[J].装甲兵工程学院 学报,2004,(1):2 1-25. 30.5 62 l72 45 82 l23 26 39 43 [3】Louden K C编译原理及实践[M】.北京:机械工业出版社,2000. [4】 张威.基于指针映射集的动态内存故障测试方法研究[J].计算 File Size指被测试程序的大小,以M为单位;Inspeciton Points指软件测试工具检测出的IP总数;Defects指经人工复 查后确定的错误总数,这是最后要提交给客户的最终结果。由 上面的实验结果可知,软件中存在的错误与文件大小成一定 相关性。该测试软件能够找出被测程序的大部分未初始化变 量的错误。 机学报,2003,(2):25-27。 [5】 Bernhard Scholz,Johann Blieberger,Thomas Fahringer.Sym- bolic pointer nalaysis orf detectnig memory leaks[R].To appear n iReal-Time Systems Journal,2002. [6】Emami M,Ghiya Hendren L J.Context-sensiitve interproce. duralpoinst-toanalysisinthepresenceoffunctionpointers[M]. ACM SIGPLAN Notices,2000,29(6):242—256. 与Reasoning公司的测试结果进行了对比,如表2所示。 4结束语 软件测试的目的是为了发现更多的错误,面向具体错误类 [7】 古乐,史九林.软件测试技术概论[M】.北京:清华大学出版社, 2o03. [8】Terrence W Pratt.程序设计语言:设计与实现[M】.第4版.北京: 电子工业出版社,2001. 型的测试方法使这一点更加突出。经过工具分析,虽然也不能 (上接第750页) 3.Retnrn SE lishing House ofTsinghna University,2005. } 3.3 Advantages [2】 Willim aFord,Willim aTopp.Data structures wiht C++[M】.Bei— jing:heT ublPishing House ofTsinghua Universiyt,2000. [3】Yu Xing-axuan.Computer algorithm[M】.he TublPishing House of Chinese Central Science nd Technolaogy Universiy,2000.t (1)he Tthought is simple nd ait is vey reasy to be implemented nd coded.a (2)Ifthe numberofpointsin Sis verybig,step 2and step 3in he maitn algorithm is executed in two computers synchronously. 【4] L Jin-yi.Discussion on n aO(n)time algorithm orf het convex hullofaplanarpoInt set[J].Computer Jourla,2002,(6):671—672. 【5】Wei Xiao-ling.Tahe variation nd aapplications ofthe“giit wrapping”algorithm[J].Journal ofthe CUN,2000,(1):8—10. 4 Conclusion hetThoughtsofthetwo algoritms areverhy simpleand easyto be implemented nd acoded.Ifthe number ofpoints in S is very big, 【6】Cheng Xiao-jun.The technology of esatblishing TIN based on onvex cshell[C].North East Mapping,200 1.6—9. [7】 YanWei-min.Data structure nd alagorithm[M】.Beijing:The ublPishingHouseofTsinghnaUniversiy,2004.t algorithms are executed synchronously. Reference Materials 【8】Jing aHong-fei.Study on fsta convex hull algorithm ofplnera [1】Zhou Ming—de.Computational geometry[M】.Beijng:iheT Pub- po set[J].Computer Projects nd aApplications,2002,20:48-49. —754・——
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- sarr.cn 版权所有 赣ICP备2024042794号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务