2/08/2006

单步调试每一段代码


尽管断言可以提示可能的问题,但是这意味着程序员需要预料代码中可能存在的问题——而程序员不可能预料到全部问题。最常用的办法还是用调试器来单步调试代码。这个优势是测试人员不具有的,他们只能使用各种各样的输入数据,然后检验输出。


但是单步测试所有的代码?


如果程序员对自己代码很自信,那么他们可以不对编写的代码进行单步测试——但是有多少人能保证自己的代码没有BUG?更不用说单步测试代码的时间和编写代码的时间相比只是九牛一毛了。


我知道习惯良好的程序员会编写异常处理代码。但是,所谓异常就意味着平常这些代码不会被执行到,所以在测试这部分代码时,可以手动编写抛出异常的代码,或者在调试器中修改保存函数返回值的变量的值,以及手动设置当前语句(但是注意这可能使得栈的状态和代码不匹配)。


应该设置断点的位置



  • 构造函数的结尾。每一个成员变量在运行到这里的时候都应该被初始化完毕,如果你在Visual C++中调试时看到一个成员变量具有0xcccccccc这样的值,那么你就忘记初始化这个成员变量了。
  • 函数的开头。如果你的函数工作不正常,检查函数的参数,看看是否符合你的函数的要求。
  • 条件分支语句。注意这不仅包含if语句,也包含隐含逻辑运算的||、&&和?:语句。这些语句的是程序流程分支的位置,而每个分支都需要被单步测试。如果分支之前的语句经过了测试,那么下一次测试的时候可以直接跳到分支的位置——当然也可以不这么跳以测试代码在不同的输入条件下的行为。

有时候需要调试发布版本的代码——调试版本的工作完全正常,但是发布版本的行为和调试版本不同。在单步调试发布版本的代码的时候,一个需要注意的问题是编译器的优化选项会造成单步调试的语句顺序和调试版本下的语句顺序略有不同。如果你觉得优化造成的语句次序颠倒使你无法调试代码,那么你可以关闭优化选项,但是为了尽可能使得调试的程序和发布的程序的行为保持一致,推荐的方法还是尝试习惯这种调试方式。


在Visual C++中,不仅可以在源代码视图进行单步调试,也可以在反汇编视图进行单步调试。在反汇编视图进行单步调试的优点是,这可以分拆?:这样的复杂语句的行为,而不是一次就跳过整个语句。


No comments: