bug存在说明什么
代码错误
需求没有完成
用户需求理解错误
设计文档中有逻辑错误
测试不足
在复现bug的时候需要控制什么
控制软件版本
控制环境相同
控制输入数据相同
调试的过程
复现错误(repreduce)
在进行错误复现的时候,要控制软件版本、运行环境、输入数据
不同的版本的spec是不一样的
不同的环境,比如不同的操作系统
在控制输入的时候,一定要尽量减小input的size
如果你不能控制输入,那么请使用推断输入和记录输入
定位错误(diagnose)
先猜想错误的位置(抽象),然后做实验进行验证
运行不同的测试用例
插入打印语句
设置断点
交换组件(将一个确保安全的组件换进来,从而暂时排除一些问题)
诊断策略1:Instrumentation(也就是插入一些诊断代码,但是这些代码并不影响程序原来的结果)
诊断策略2: Divide and Conquer (分治)
诊断策略3:Slicing(将对最终值没有贡献的代码屏蔽掉)
诊断策略4:focus on difference(使用版本控制系统,找出是在哪个commit之后出现了bug),可以尝试使用一下git bisect命令(这是一个对历史版本进行二分查找的工具)。当然也会有其他方面的差异:软硬件环境、jvm参数配置、输入文件……
诊断策略5:Symbolic Debugging(获得符号化的结果,也就是将执行的抽象结果写出来)
修改错误(fix)
一边修改,一边测试
一次一个change
反省(reflection)
从理解客户需求、软件架构和设计、测试设计、对底层架构的理解上入手进行反思
调试方法和工具
查看内存导出文件
查看程序崩溃的时候内存状况,这种方法效率非常低
栈跟踪
使用打印输出语句
logging
编译器警告信息
设置断点
watchpoint
将测某个内存地址或者是某个变量内存状态