[工学]南京大学软件学院计算系统基础讲义第5章

上传人:tia****nde 文档编号:70512730 上传时间:2019-01-17 格式:PPT 页数:33 大小:588.31KB
返回 下载 相关 举报
[工学]南京大学软件学院计算系统基础讲义第5章_第1页
第1页 / 共33页
[工学]南京大学软件学院计算系统基础讲义第5章_第2页
第2页 / 共33页
[工学]南京大学软件学院计算系统基础讲义第5章_第3页
第3页 / 共33页
[工学]南京大学软件学院计算系统基础讲义第5章_第4页
第4页 / 共33页
[工学]南京大学软件学院计算系统基础讲义第5章_第5页
第5页 / 共33页
点击查看更多>>
资源描述

《[工学]南京大学软件学院计算系统基础讲义第5章》由会员分享,可在线阅读,更多相关《[工学]南京大学软件学院计算系统基础讲义第5章(33页珍藏版)》请在金锄头文库上搜索。

1、第五章 测试和调试,系统缺陷,1994年,美国数学家托马斯奈斯利,发现Pentium处理器计算浮点数除法存在缺陷(FDIV Bug) 31457274195835/3145727的计算结果是4195579,而不是4195835。 Intel大量回收1994年12月之前生产的第一代Pentium产品,4.75亿美元的赔偿款,千年虫,二十世纪六、七十年代,存储设备非常昂贵的 采用两位而不是四位数字表示年份。 一个图书馆计算机系统 一位读者在1999年12月1日借了一本书,99 2000年,这位读者还书时,系统判断是否超期? 关于日期的运算发生错误,系统运行出现问题。 “2000年问题”、“千年虫”

2、。据统计,全世界为解决“2000年问题”花出的费用超过数亿美元。,缺陷、测试、调试,程序中的错误,缺陷(bug) 找出缺陷的过程,测试 去除错误的过程,调试(debug) 在程序被投入使用之前,必须尽可能的进行彻底测试和调试。,几乎每个大型程序都存在一些缺陷 测试工作往往会带来很高的时间和经济成本。 有调查显示:一个熟练的程序员花在调试代码上的时间和花在写程序上的时间一样多。 许多大型软件项目开发都会延期,并且严重超出预算,其中一个重要原因就是软件中的缺陷。 需要一些构建程序的更好的办法,使得在测试之前就能避免问题或者发现问题。,15-6,错误类型,语法错误 违反了编程语言有关规则 编译器能够

3、精确指出错误出现在哪一行 语义及逻辑错误 是指代码没有语法错误,可以运行,但是得不到正确的结果。 需要跟踪程序的运行过程才能发现。,15-7,语法错误,编译器报告的错误位置,有时会有偏离。 编译器常常会针对某个错误,发出一系列的错误信息报告。 常见的语法错误 语句末尾漏写分号; 使用未经声明的变量; 括号不匹配; 字符串没有结束符; 赋值运算符左面不是变量 main () int i int j; for (i = 0; i = 10; i+) j = i * 7; printf(“%d x 7 = %dn“, i, j); ,missing semicolon,语义及逻辑错误,当程序在语法上

4、是正确的,可以运行,却得不到正确的结果 语义错误,程序的运行结果与程序员的期望不同 逻辑错误,程序按照程序员所设计的有缺陷的算法运行,运行结果与程序员的期望相同。,15-9,语义错误,往往由于对程序中的语义的理解与编译器理解的不同造成的。 常见的语义错误 赋值运算符与相等运算符用错; 无限循环; 在if、while或for结构后面使用多余的分号; 错误地使用了关系运算符; 计算或将一个大类型的数转换成小类型时,数据的值超出了表示范围; 运算符优先顺序错; else搭配不当; off-by-one(偏一)错误,通常指for循环的次数多或少一次; 将无关代码放到循环体中; 使用整数除法。 main

5、 () int i int j; for (i = 0; i = 10; i+) j = i * 7; printf(“%d x 7 = %dn“, i, j); ,missing braces, so printf not part of if,15-10,逻辑错误,不正确的程序设计的结果。 程序本身准确的按照程序员所设计的算法运行了,但是这种设计本身有缺陷。 这种错误非常隐蔽,需要经过多次运行程序才会被发现。 当它们被检测到并且被隔离后,仍然很难修复。 在编写代码之前的设计阶段,通过规划,这种错误经常能够被减少甚至消除。 “2000年问题”,15-11,逻辑错误,#include int

6、main() int year; printf(“Input a year (i.e., 1996): ”); scanf(“%d”, ,测试,一般说来,就是使用不同的输入组合进行试验(为了模拟在真实的情况下软件将要遇到的问题),对程序的输出结果进行正确性检查。 现实世界中的软件在发布之前都需要经过无数次的试验。 理想情况 通过在所有可能的输入条件下,检查程序的操作,对其进行测试。 实际情况 对所有的输入情况进行测试是不可能的。,示例,判断从A到B之间某个数字是不是素数 A和B都是从键盘输入的整数,数值范围在-2147483648到2147483647之间(-231231-1) (232)2种

7、可能的输入组合 一秒钟进行一百万次测试,需要50万年 应该对哪些输入组合进行测试呢? 随机的选择一些输入,能够揭示出这个程序的错误所在。,测试,黑盒测试 检查程序是否符合其规格说明 白盒测试 确保每一行代码都被测试过。,黑盒测试,检查程序是否满足其输入和输出规格说明。只关心这个程序是做什么的,而不关心它是怎么做的。 自动测试过程 创建一个程序,可以自动运行被测试的程序,在运行中提供一些随机的输入,检查输出是否符合规格说明,然后重复这个过程。 构建一个检查器程序,它与被测试的程序不同,但执行类似的计算。,黑盒测试,不可能知道哪几行代码已被测试过,哪些还没被测试任何一行没有经过测试的代码都可能是有

8、错误的。 当规格说明不是很具体的时候,有时很难使用。 只能在软件完成时开始为了被测试,软件必须被编译并且必须满足规格说明中的一部分。,白盒测试,白盒测试的目标是保证每一行代码都要经过某个级别的测试。 检查代码 使用未经正确初始化的变量; 变量是否被赋予不同类型的值; 变量声明错误:类型、存储类;初始化;未引用过;模块中显示声明? 计算错误:混合类型;溢出;除数为0;精度丢失;优先级 比较错误:精度 控制流程错误:无限循环;从不执行的循环,白盒测试,需要修改被测试的代码 在代码中添加printf语句,以便观察内部变量的值,从而可以检查程序是否按照预期运行。 “断言”是一种普遍应用的白盒测试技术。

9、,断言,在程序中的特定部位,插入一些用来检测错误的代码,当检测到某个错误状态时,这些代码就会打印出一个警告消息,显示该状态的一些相关信息,或者使程序提前终止。 在程序执行中使这些语句得以证实,从而使程序的运行特性得到证实断言。,示例,#include int main() int dividend; int divisor; int result; printf (“Enter the dividend: “); scanf (“%d“, ,6 - 21,调试,迷路时,怎么做? 毫无目的地徘徊,希望找到回去的路 回到一个“熟悉”的位置,然后,使用地图,根据地图提供的方向,不断的比较你所处的位置

10、(从你看到的路标来断定)和地图所指的位置,直到到达你的目的地 调试程序与之类似。 留意你位于哪里,再比较一下你想去哪里,跟踪程序。 跟踪已经被执行的代码以及每条语句执行后得到的结果。 比较每条语句做了什么和期望要它做什么时,将会在程序中发现错误。,15-22,调试技术,专门的技术 查看源代码。 源代码的区域很小而且对代码非常熟悉的话,就适合采用这种方法。 在代码中插入一些语句,在执行期间输出相关信息。 使用printf语句来输出那些被认为在找错误上有用的重要变量的值。 在代码中不同的地方加入printf语句,以此来查看程序的控制流程是否正确运行。 需要重新编译、执行 插入的代码bug,#inc

11、lude int main() int i; int n = 6; int result = 1; for (i = 1; i n; i+) result = result * i; printf (“%dn“, result); ,for (i = 1; i n; i+) result = result * i; printf (“%dn“, result); ,源水平调试器,源水平调试器,一个允许程序在一个可控的环境下执行的工具,在其中,程序的执行的所有方面都可以被程序员控制和检查。 检查:检查,设置变量的值 控制:跟踪,断点,单步执行 允许一次执行程序的一条语句,并且可以检查变量的值等信

12、息。,断点,在程序执行的过程中,指定一些点,在这些点,程序可以被临时停止检查或者修改程序的状态。 在某个特定行添加一个断点。当执行到那一行时,程序的执行被及时冻结,检查所有的与程序有关的事物。,断点,条件断点:只有当一个特定的条件成立时才暂停于某一行。对于隔离出那些被怀疑执行有错误的特定情况是非常有用的。 观察点:在任意一个特定条件为真的地方都能使程序停止。 例如,只要当变量i等于4时,程序就停止执行。调试器在任何使i等于4的语句处停止执行。 观察点不是与代码的任何单独一行有关的,而是应用于每一行。,单步,一旦调试器到达一个断点,它会临时挂起程序的执行,并等待下一条命令。 从断点开始,一次处理

13、一条语句单步。 执行当前的源代码行,然后再次将程序挂起,监视当前程序。 检查变量的值 确定程序的控制流程是否做了被期待做的事情,显示值,一般说来,在断点处可以检查程序的所有执行状态。 使用鼠标在源代码窗口指向一个变量,使得弹出窗口显示这个变量的当前值。 输入想要检查的变量名。,溢出?,#include int main() int i; int n; int result = 1; scanf (“%d”, ,正确编程,在错误还没成为错误之前,就能被捕获到。 明确规格说明 很多错误都源于不完善的程序规格说明。规格说明有时不能涉及所有可能的运行场景,因此就留下一些情况需要程序员来解释。 需求 模块化设计 把简单的、预先测试过的和可以运行的组件构建为程序,函数和库 设计,防御性程序设计,写注释 写注释能让程序员对他写的代码进行思考。 在这个过程中,可能会发现一个特别的情况或是一个最后会让代码崩溃的运行条件被忽略。 采用一致的编码风格 对齐左右大括号能够识别出那些缺少括号的简单的语义错误。,避免假设 假设输入的数据总是在某个范围内。如果这个假设不在这个程序的规格说明里,那么出现错误的可能性就产生了。 写避免假设的代码,或者至少使用断言,并抽样调查说明假设何时不成立。 避免全局变量 依赖编译器 检查程序中可疑的代码 警告信息,

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号