如何对C语言设计合适的程序调试方案
让我们来分析并设计对如下程序进行调试的具体方法与手段(实际上,对不同的程序,都需要在分析其执行结果以及其程序编写结构的基础上,来设计相应的对其进行具体调试的方法与手段,宗旨是想方设法逐步缩小“侦察”范围,直到最后找到出错位置)。
该程序除main外,还有一个自定义函数f。若已经能确认调用f函数前计算出的res值(或s、d、q或r其中之一的结果值)不正确的话,则可像上一程序那样,在计算出res变量值的下一行(或在靠前一些的某一行)处设置断点,看到达那一断点处是否一切正常。若到达断点处的数据结果已经不正常的话,错误已经出现(出现在跟前或出现在前面,从而找到了错误或者缩小了“侦察”范围);若断点处仍然正常,可断言错误出现在后面,而后,一:可又一次通过鼠标光标往更靠后一些的适当位置设置新断点,再一次“Debug -> Run to Cursor”(一下向后“迈”过了许多行,再继续“侦察”);二:通过“单步执行”(Debug -> StepOver),在重点怀疑的那一块地方仔细地逐行进行“侦察”。
注意,“Step Over”不会“跟踪”进入f函数内部,若怀疑f函数可能有问题的话,要通过使用“Debug -> Step Into”进入f内部再进行细致调试(在不遇到函数调用的地方,“Step Over”与“Step Into”的功能是相同的。若通过“Step Into”进入到函数内部,单步执行若干步之后,若发现不再需要进行单步调试的话,可通过“Step Out”从函数内部返回到调用语句的下一语句处)。
作为练习,请读者利用这一程序对上述的调试方法与手段进行多方面的灵活使用与体验!可以看出,程序调试是一件很费时费力而又非常细致的工作,需要耐心,要通过不断的实践来总结与积累调试经验。至于VC6.0提供的其他调试方法与手段,这儿就不一一介绍了。
前面也提到过,通过“Run to Cursor”所设置并到达的断点是一个临时性的断点。实际上,VC6还提供设置与清除固定性断点的方法。设置固定性断点最简单的方法是:在某一程序行处,单击鼠标右键,在菜单中选择“Insert/Remove Breakpoint”项(通过左键单击该选项,此时该行前将出现一个圆形的黑点标志,意味着已经将该行设置成了固定断点)。
清除固定性断点的方法为:在具有圆形黑点标志的固定断点行处,单击鼠标右键,在菜单中选择“Remove Breakpoint”项(通过左键单击该选项,此时该行前的那一个圆形黑点标志将消失,意味着已经清除了该固定断点)。
设置了固定性断点后,通常通过“Build -> Start Debug -> Go”或“Debug -> Go”选项使程序开始执行,直到遇到某断点或遇到程序结束而停止。
还要说明的是,可以随时设置任意多个固定性断点,也可以随时清除它们。通过使用菜单选项“Edit -> Breakpoints”,会出现一个对话框,在其中的“Break at”文本框中键入要设置断点的程序行的行数信息(但通常是先通过鼠标光标选定某一程序行,再利用菜单选项进入上述对话框,而后通过点击“Break at”文本框右边的小三角按钮,并选定系统自动提供的程序行的行数,以免自己要真正地去数清楚那一行的行数),也能够在指定行处设置一个固定性断点(通过OK按钮确定);如果要清除某断点,可在“Breakpoints”列表栏中先选定它,之后单击Remove按钮。实际上,除位置断点外,通过“Edit -> Breakpoints”,还可以设置数据断点,消息断点,以及条件断点等,这儿就不再细说了。
VC6是一个极为庞大的开发工具,我们所介绍的仅仅是一些基本的应用,使用这些应用已经可以完成书中所涉及到的例子和作业,有兴趣的读者可通过参看其他有关介绍VC6的资料或书籍来进行进一步的学习与提高。
该程序除main外,还有一个自定义函数f。若已经能确认调用f函数前计算出的res值(或s、d、q或r其中之一的结果值)不正确的话,则可像上一程序那样,在计算出res变量值的下一行(或在靠前一些的某一行)处设置断点,看到达那一断点处是否一切正常。若到达断点处的数据结果已经不正常的话,错误已经出现(出现在跟前或出现在前面,从而找到了错误或者缩小了“侦察”范围);若断点处仍然正常,可断言错误出现在后面,而后,一:可又一次通过鼠标光标往更靠后一些的适当位置设置新断点,再一次“Debug -> Run to Cursor”(一下向后“迈”过了许多行,再继续“侦察”);二:通过“单步执行”(Debug -> StepOver),在重点怀疑的那一块地方仔细地逐行进行“侦察”。
注意,“Step Over”不会“跟踪”进入f函数内部,若怀疑f函数可能有问题的话,要通过使用“Debug -> Step Into”进入f内部再进行细致调试(在不遇到函数调用的地方,“Step Over”与“Step Into”的功能是相同的。若通过“Step Into”进入到函数内部,单步执行若干步之后,若发现不再需要进行单步调试的话,可通过“Step Out”从函数内部返回到调用语句的下一语句处)。
作为练习,请读者利用这一程序对上述的调试方法与手段进行多方面的灵活使用与体验!可以看出,程序调试是一件很费时费力而又非常细致的工作,需要耐心,要通过不断的实践来总结与积累调试经验。至于VC6.0提供的其他调试方法与手段,这儿就不一一介绍了。
#include <stdio.h> int f(int a){ int b, c; b = a + 5; c = 2*b + 100; return c; } void main(){ int x=3, y=5; int s, d, q, r, res, z; s = x + y; d = x - y; q = x / y; r = x % y; res = s + 2*d + 3*q + 4*r; printf("res=%d\n", res); z = f(36); printf("z=%d\n", z); }
前面也提到过,通过“Run to Cursor”所设置并到达的断点是一个临时性的断点。实际上,VC6还提供设置与清除固定性断点的方法。设置固定性断点最简单的方法是:在某一程序行处,单击鼠标右键,在菜单中选择“Insert/Remove Breakpoint”项(通过左键单击该选项,此时该行前将出现一个圆形的黑点标志,意味着已经将该行设置成了固定断点)。
清除固定性断点的方法为:在具有圆形黑点标志的固定断点行处,单击鼠标右键,在菜单中选择“Remove Breakpoint”项(通过左键单击该选项,此时该行前的那一个圆形黑点标志将消失,意味着已经清除了该固定断点)。
设置了固定性断点后,通常通过“Build -> Start Debug -> Go”或“Debug -> Go”选项使程序开始执行,直到遇到某断点或遇到程序结束而停止。
还要说明的是,可以随时设置任意多个固定性断点,也可以随时清除它们。通过使用菜单选项“Edit -> Breakpoints”,会出现一个对话框,在其中的“Break at”文本框中键入要设置断点的程序行的行数信息(但通常是先通过鼠标光标选定某一程序行,再利用菜单选项进入上述对话框,而后通过点击“Break at”文本框右边的小三角按钮,并选定系统自动提供的程序行的行数,以免自己要真正地去数清楚那一行的行数),也能够在指定行处设置一个固定性断点(通过OK按钮确定);如果要清除某断点,可在“Breakpoints”列表栏中先选定它,之后单击Remove按钮。实际上,除位置断点外,通过“Edit -> Breakpoints”,还可以设置数据断点,消息断点,以及条件断点等,这儿就不再细说了。
VC6是一个极为庞大的开发工具,我们所介绍的仅仅是一些基本的应用,使用这些应用已经可以完成书中所涉及到的例子和作业,有兴趣的读者可通过参看其他有关介绍VC6的资料或书籍来进行进一步的学习与提高。