什么是bug,什么是debug
头疼的问题
学计算机的人最头疼的东西就是bug了,我们经常为了找一个bug话费数小时的时间,而bug的官方定义是程序的失误,这一失误有会导致程序表现得漫无目的或者没有计划性。而当有人向你报告一个bug时,至少有数十人已经遇到过同样的问题,只不过没跟你说而已。越早发现bug越好
前面讲了防御式编程和测试对于提高程序正确性,健壮性的作用,而当防御式编程和测试都无法挡住bug时,debug就不得不做了。
关于debug步骤
Defensive Programming → Testing → Debugging
Debug是测试的后续步骤:测试发现问题,debug消除问题debug的目的是寻求错误的根源并且消除此错误,而这会导致debug占用了大量的开发时间。下面是统计:
debug通常操作
我们在debug时一般从不正常症状下手,在不正常症状与原因之间建立联系,通过回归测试判定bug已被解决,图上标注起来很容易,但是debug实际上是有点困难的。
debug困难的原因
当代的程序趋于复杂,所以代码与代码之间会出现高耦合的情况,症状”和“原因”可能相隔很远,或者,当其他bug被修复的时候,该bug消失了,还有四舍五入造成的不准确等非错误因素,另外还有人工错误1导致bug的症状难以有效追踪。有些症状是由计时/定时等原因导致的,另外,难以重现出错时的输入数据。而且,由于外部软硬件环境变化,可能会导致间歇性的症状,还有分布式导致的问题。所以,错误原因五花八门,必须在长期持续的代码训练中练成一身debug的看家本领。
debug流程
debug步骤
重现:找到可靠方便地重现错误的方法。
诊断:对可能的错误做出假设并且一一试验直到你确定你找到错误根源为止。
修复:设计思路,修复这个问题,避免回退,并且保持或者提升软件一贯的质量。
反思:举一反三,找出问题所在,思考有无类似的问题并且怎样才能让类似的问题不重现。
debug占用大部分开发时间,而错误定位又占用绝大部分(高达95%)的debug时间,于是自动化错误定位成为科学研究。
debug的科学方法:
常用方法:假设-检验
- 收集bug相关数据。
- 观察数据,做出bug原因的假设。
- 决定如何验证。
- 通过工具验证假设是否成立。
重现bug
从最小的测试用例集开始复现错误,确定有哪些因素跟bug相关,将这些因素找出来并变化它们的值,我们找出bug是为了用户可以正常地使用程序,但是,用户使用程序的软硬件环境会有不同,所以,要确保你的bug复现环境跟用户发现bug的环境尽可能保持一致。
在重现bug的时候,要注意软件版本,软件的运行环境和输入数据,这些因素要尽量和用户保持一致。
诊断bug
1. 测量
插桩代码:不影响软件的行为,提供对软件行为的深入了解比如说logging。测量不仅限于简单的输出
2.分治
如果你的程序由一个个可以分开运行的模块组成,那么我们一次把每个模块设置成能够运行和不能够运行的状态,去找bug到底是在哪个模块中出现。这就类似于二分法,先把整个区间一分为二,然后去找bug在哪个区间中,再把找到bug的区间一分为二,然后再去找bug,再分…直到找到bug为止。防狼围栏算法就是这个思路:
3.切片
把程序的逻辑框图画出来,猜测bug所在的片段,并且做尝试。