
1.5 程序调试
程序调试是程序设计中一个很重要的环节,一个程序一般要经过很多次调试才能保证基本正确。程序调试分为源程序语法错误的修改和程序逻辑设计错误的修改两个阶段,编译器只能找出源程序的语法错误,程序的逻辑设计错误只能靠程序员利用调试工具手工检查和修改。
1.5.1 查找源程序中的语法错误
语法错误分为一般错误(error)和警告错误(warning)。当出现error错误时将不会生成可执行程序,而出现warning错误时能够生成可执行程序,但程序运行时可能发生错误,严重的warning错误还会引起死机现象。warning错误比error错误更难于修改,应该尽量消除warning错误。
如果程序有语法错误,则在执行编译、链接命令时,Visual C++编译器将在输出窗口中给出语法错误提示信息,但链接错误提示信息不能给出错误发生的具体位置。
在输出窗口中双击错误提示信息或按F4键可以返回到源程序编辑窗口,并通过一个箭头符号定位到产生错误的语句。
在运行阶段,当运行环境检测到一个不可能执行的操作时,也会发生错误。例如,除以零的错误。在不可预料的事情发生时或者在程序中一条语句不能正常执行时,发生运行错误。这种错误在应用程序开始执行之后发生。
需要说明的是,编译器给出的错误提示信息可能不十分准确,并且一处错误往往会引出若干条错误提示信息。因此,修改一个错误后应该马上进行程序的编译。通过重复的编译可使程序中的语法错误越来越少,直至所有的语法错误都被修改,从而得到一个可执行程序。
1.5.2 跟踪调试程序
即使源程序没有语法错误,但最后生成的可执行程序也没有像预想的那样运行,这类程序设计上的错误被称为逻辑设计错误或缺陷(bug)。跟踪调试程序是查找此类逻辑设计错误方法中最常采用的动态方法。跟踪调试的基本原理就是在程序运行过程的某一阶段观测程序的状态。在一般情况下程序是连续运行的,所以我们必须使程序在某一点停下来。首先,我们所做的第一项工作就是设立断点;其次,再运行程序,当程序在断点设立处停下来时,再利用各种工具观测程序的状态。程序在断点停下来后,有时需要按用户要求控制程序的运行,以便进一步观测程序的流向。
1. 设置断点
利用Visual C++ 6.0提供的集成调试环境,可以设置从简单到复杂的各种断点。选择Edit菜单下的Breakpoints菜单项后,系统显示Breakpoints对话框,如图1-8所示。从图中可以看到Breakpoints对话框包含三个选项卡,分别为按位置、按表达式的值和按窗口消息三种设置断点的方式。

图1-8 Breakpoints对话框
Location选项卡用于设置位置断点。该断点是最常用的一个无条件断点,也是默认的断点类型。程序执行时遇到这种断点,只是简单地停下来。
在Build MiniBar工具栏中,单击Insert/Remove Breakpoint按钮可以快捷地在某个程序行插入/移除断点。
2. 控制程序运行
当设置完断点后,程序就可以进入Debug状态,并按要求来控制程序的运行,其中有四条命令:Step Over、Step Into、Step Out和Run to Cursor。
我们可以通过用鼠标单击工具栏按钮或使用热键来控制程序的运行。
3. 观察数据变化
在调试过程中,用户可以通过Watch和Variable窗口查看当前变量的值。这些信息可以反映程序运行过程中的状态变化以及变化结果的正确与否,可以反映程序是否有错,再加上人工分析,就可以发现错误所在。
1.5.3 调试器
为了查找和修改程序中的逻辑设计错误,Visual C++ IDE提供了重要的调试工具——Debug。单击Build→Start Debug菜单中的菜单项,可以启动Debug。Start Debug子菜单中有Go、Step Into、Run to Cursor及Attach to Process菜单项,它们的功能见表1-10。
表1-10 Start Debug菜单中的菜单项和功能

调试过程开始后,Debug主菜单取代Build主菜单出现在菜单栏中,同时出现一个可停靠的Debug工具栏和一些调试窗口,如图1-9所示。将光标放在程序中的某个变量名上,它的当前值就会显示出来。在Debug菜单上有许多菜单项可以控制程序的执行,见表1-11。

图1-9 Debug界面
表1-11 Debug菜单中的主要菜单项和功能

Variable窗口用于观察和修改变量的当前值,Debug可根据当前程序运行过程中变量的变化情况自动选择应显示的变量。用户可以在Variable窗口的Context下拉框选择要查看的函数,然后Debug会在窗口中显示函数局部变量的当前值。该窗口中有三个选项卡,Auto选项卡中显示当前语句或前一条语句中变量的值和函数的返回值,Locals选项卡中显示当前函数局部变量的名称、值和类型,this选项卡以树形方式显示当前类对象的所有数据成员,单击+号可展开this指针所指对象。
Watch窗口用于观察和修改变量或表达式的值。它有Watch1、Watch2、Watch3和Watch4四个标签,在每个标签中,用户都必须手工设置要观察的变量或表达式。