调试(Debug)
软件调试是在进行了成功的测试之后才开始的工作,它与软件测试不同,调试的任务是进一步诊断和改正程序中潜在的错误。
注:
以问题为中心
以错误为导向
调试活动由两部分组成:
u 确定程序中可疑错误的确切性质和位置
u 对程序(设计,编码)进行修改,排除这个错误
注:
测试和调试密不可分
测试是为了发现问题
调试时为了解决问题
调试工作是一个具有很强技巧性的工作
软件运行失效或出现问题,往往只是潜在错误的外部表现,而外部表现与内在原因之间常常没有明显的联系,如果要找出真正的原因,排除潜在的错误,不是一件易事。
可以说,调试是通过现象,找出原因的一个思维分析的过程。
调试步骤:
(1) 从错误的外部表现形式入手,确定程序中出错位置
(2) 研究有关部分的程序,找出错误的内在原因
(3) 修改设计代码,以排除这个错误
(4) 重复进行暴露了这个错误的原始测试或某些有关测试。
注:
由外而内
由现象到本质
由结果到原因
从技术角度来看查找错误的难度在于:
u 现象与原因所处的位置可能相距甚远
u 当其他错误得到纠正时,这一错误所表现出的现象可能会暂时消失,但并为实际排除
u 现象实际上是由一些非错误原因(例如,舍入不精确)引起的
u 现象可能是由于一些不容易发现的人为错误引起的
u 错误是由于时序问题引起的,与处理过程无关
u 现象是由于难于精确再现的输入状态(例如,实时应用中输入顺序不确定)引起
u 现象可能是周期出现的,在软,硬件结合的嵌入式系统中常常遇到
几种主要的调试方法
调试的关键在于推断程序内部的错误位置及原因,可以采用以下方法:
1.强行排错:
这种调试方法目前使用较多,效率较低,它不需要过多的思考,比较省脑筋。例如:
u 通过内存全部打印来调试,在这大量的数据中寻找出错的位置。
u 在程序特定位置设置打印语句,把打印语句插在出错的源程序的各个关键变量改变部位,重要分支部位,子程序调用部位,跟踪程序的执行,监视重要变量的变化
u 自动调用工具,利用某些程序语言的调试功能或专门的交互式调试工具,分析程序的动态过程,而不必修改程序。
应用以上任一种方法之前,都应当对错误的征兆进行全面彻底的分析,得出对出错位置及错误性质的推测,再使用一种适当的调试方法来检验推测的正确性。
2.回溯法调试:
这是在小程序中常用的一种有效的调试方法,一旦发现了错误,人们先分析错误的征兆,确定最先发现“症状“的位置
然后,人工沿程序的控制流程,向回追踪源程序代码,直到找到错误根源或确定错误产生的范围,
例如,程序中发现错误处是某个打印语句,通过输出值可推断程序在这一点上变量的值,再从这一点出发,回溯程序的执行过程,反复思考:“如果程序在这一点上的状态(变量的值)是这样,那么程序在上一点的状态一定是这样···“直到找到错误所在。
3.归纳法调试:
归纳法是一种从特殊推断一般的系统化思考方法,归纳法调试的基本思想是:从一些线索(错误征兆)着手,通过分析它们之间的关系来找出错误
u 收集有关的数据,列出所有已知的测试用例和程序执行结果,看哪些输入数据的运行结果是正确的,哪些输入数据的运行经过是有错误的
u 组织数据
由于归纳法是从特殊到一般的推断过程,所以需要组织整理数据,以发现规律
常以3W1H形式组织可用的数据
“What“列出一般现象
“Where“说明发现现象的地点
“When“列出现象发生时所有已知情况
“How“说明现象的范围和量级
“Yes“描述出现错误的3W1H;
“No“作为比较,描述了没有错误的3W1H,通过分析找出矛盾来
u 提出假设
分析线索之间的关系,利用在线索结构中观察到的矛盾现象,设计一个或多个关于出错原因的假设,如果一个假设也提不出来,归纳过程就需要收集更多的数据,此时,应当再设计与执行一些测试用例,以获得更多的数据。
u 证明假设
把假设与原始线索或数据进行比较,若它能完全解释一切现象,则假设得到证明,否则,认为假设不合理,或不完全,或是存在多个错误,以致只能消除部分错误
4.演绎法调试:
演绎法是一种从一般原理或前提出发,经过排除和精华的过程来推导出结论的思考方法,演绎法排错是测试人员首先根据已有的测试用例,设想及枚举出所有可能出错的原因作为假设,然后再用原始测试数据或新的测试,从中逐个排除不可能正确的假设,最后,再用测试数据验证余下的假设确是出错的原因。
u 列举所有可能出错原因的假设,把所有可能的错误原因列成表,通过它们,可以组织,分析现有数据
u 利用已有的测试数据,排除不正确的假设
仔细分析已有的数据,寻找矛盾,力求排除前一步列出所有原因,如果所有原因都被排除了,则需要补充一些数据(测试用例),以建立新的假设。
u 改进余下的假设
利用已知的线索,进一步改进余下的假设,使之更具体化,以便可以精确地确定出错位置
u 证明余下的假设
调试原则
n 在调试方面,许多原则本质上是心理学方面的问题,调试由两部分组成,调试原则也分成两组。
n 确定错误的性质和位置的原则
u 用头脑去分析思考与错误征兆有关的信息
u 避开死胡同
u 只把调试工具当做辅助手段来使用,利用调试工具,可以帮助思考,但不能代替思考
u 避免用试探法,最多只能把它当做最后手段
n 修改错误的原则
u 在出现错误的地方,很有可能还有别的错误
u 修改错误的一个常见失误是只修改了这个错误的征兆或这个错误的表现,而没有修改错误的本身。
u 当心修正一个错误的同时有可能会引入新的错误
u 修改错误的过程将迫使人们暂时回到程序设计阶段
u 修改源代码程序,不要改变目标代码