ACM_调试技巧(不定期更新)

来源:互联网 发布:云计算与应用就业前景 编辑:程序博客网 时间:2024/06/06 03:36

对于调试,一般来说指的是逻辑错误,因为语法错误编译器可以帮你检查出来,但有一些陷阱语法编译器却很难检测出来,毕竟C/C++语言比较灵活。

VC++6.0

在讲解之前,先讲一下调试常用快捷键。

调试快捷键Ctrl + F7编译F7连接Ctrl + F5运行F5调试运行Shift+ F5终止调试F9设置/取消断点F10步进F11步入












对我来说,编译、运行、连接这三个快捷键很少用到,因为VC有工具栏嘛...而且找到快捷键我都已经用鼠标点了...=__=
回到正题,8个快捷键剩下来我使用得最多的就是F9、F10和F11。
F9 断点,就是我们可以在程序的某一行设置一个标记,使得我们在调试的时候,一旦遇上断点,程序就停下来,我们就可以通过观察变量的值来查找程序的错误。
F10 步进, 程序一行一行的运行。
F11  步入,跟F10功能类似,只不过F11遇到函数的时候,会跳进函数里执行,注意两者的区别
好了,说了那么多理论的东西,我们来举个例子来讲解一下如何调试吧。
源代码如下:
#include<stdio.h>int main(){int a,b,c;scanf("%d%d\n",&a,&b);c = a + b;printf("a + b = %d\n",c);return 0;}

对于刚学C来说,这个程序看起来并没有什么错误的地方,但是我们运行一下发现莫名其妙的东西出现了.... 如下图:

为什么我们输入10 20后回车后结果还是显示不出来?直到我们随便输入一个数才能显示出来...是我们输入有误还是我们编写代码有误?答案就由我们自己亲手调试来找出来吧!
我们使用F10来调试。

我们直接按F10,程序跳到第一个花括号那里(左边黄色小箭头指明程序运行到哪一行),如图:


再按下F10后,程序来到了输入语句scanf这里,如下图:


我们发现无论我们按多少次F10,程序也不能执行下一句...
这是因为程序需要我们从DOS窗口中输入两个整数。我们来到DOS窗口输入两个整数回车,如下图:


我们重新来到VC窗口继续按F10,发现黄色小箭头还是一直指着scanf这条输出语句。
从这里我们可以判断,我们输入没有错,但是程序执行不下去。
于是我们分析scanf这条语句,发现原来在格式化输入格式时我们习惯性的写多了一个\n,我们决定删除它试试。

先终止调试,按下Shift + F5 ,然后修改源代码,继续我们刚才的步骤,来到scanf语句,输入在DOS窗口中两个整数,回车....
再切换到VC窗口,发现黄色小箭头已经指向输入语句的下一句了耶...


我们继续按两下F10,来到return语句,再观察一下DOS窗口,程序结果已经显示出来了耶...


好了,基本上F10的功能可以通过上述例子得以掌握。

通过上述例子我们掌握了当遇到程序运行结果不是我们所预想的时候,我们可以进行调试,通过调试可以分析到错误的来源。

下面我们以一个较为复杂的例子,来讲述其余的调试快捷键的用处(F9,F11),同时介绍如何使用Watch窗口来观察我们变量的取值。
例子源代码如下:
#include<stdio.h>void swap(int a, int b){int tmp;tmp = a;a = b;b = tmp;}int main(){int a,b;scanf("%d%d",&a,&b);swap(a,b);printf("a = %d\nb = %d\n",a,b);return 0;}

程序想法很简单,输入两个数,交换后输出。
但是...程序结果却跟我们想法不一样...

我们依照上面的调试方法(F10)来试试...发现,当到了swap函数调用的时候按了F10,函数就直接完成了...
我们根本不知道函数的运行情况到底是怎样的....
这时我们解决的方法有两个:
一:运用F9断点。
二:运用F11步进到swap函数。
我们分别来说一下吧:
方法一:运用断点(F9)。
我们将光标定位在swap函数里的第一条语句 tmp = a; 
然后按下F9,此时该行前面会有一个小红圈,这时断点设置成功(将光标移到断点处再按一次F9即可取消断点)。如图:


断点设置成功后,我们可以直接使用调试运行(F5)的快捷键了,直接按下F5,在DOS窗口输入两个数后,程序就自动在我们刚才设置断点的地方停住了,哈哈,很神奇吧!

这样,程序进入了swap函数里了。


方法二:运用F11步进到swap函数。

我们使用F10的,将程序运行到swap函数的那条语句中:



这时,我们下F11,我们发现,程序并没有像F10那样运行到输出语句,而是进入了swap函数里面去了。

这里,就是F10与F11调试功能的差异了。

好了,进入了swap函数,我们运用F10来看看,局部函数里面的a,b的值得到底是如何变化的。

这是我们运用一个调试窗口Watch,调试时候默认设置在位于VC右下角部分,如图:


左边的是VC自动提供的课显示一个最近改变的变量的窗口,右边的即是Watch,我们可以在Name这一栏填入我们自己需要跟踪的变量,这里填入变量a、b和tmp,如图:


我们使用F10调试命令,swap函数返回前的执行过程(注意,a,b变量属于swap函数)如下图:

    +   

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

       

  

我们发现,函数里的a,b变量的确改变了呀,为什么我们输出的却不是我们所期望的呢?我们再按一次F10,可跳出swap函数,这时我们可以发现函数里交换了的的a,b值,跳到函数外就变回原来那样了...

读者可以自行分析一下错误所在的地方....

其实我们可以看到,我们的函数使用了传值的方式传参了,这里我们改为传地址的形式,同时修改调用时传递的形参是参数地址,即可在swap函数里改变了我们传入的参数了。

修改程序后,运行结果:



好了,这个例子也到这里了...

总结一下:

F9可以让你调试的时候直接运行到你所想要的地方,例如我们可以在输入语句后,初始化语句后设下一个断点...这样可以剩下我们一步步按下F10的时间。

F11可以让我们深入到我们自己写的函数里面去,通过观察分析,可以找到函数里到问题的根源,从而改正错误。

Watch调试窗口,可以很方便的使我们观察变量的值,我们可以预先估算变量将会变化的值,然后执行语句,通过判断可得知表达式以及一些逻辑运算是否符合我们所期望的要求,不过Watch窗口要注意一下的就是可见域的问题,当你进入了一个函数,Watch窗口的可见域就是你当前的函数以及一些全局变量,千万不要与其他里同名的变量名混淆了


VC++6.0暂时就写到这里了,有空的话将更新Code::Blocks的的调试方法,其实调试起来也大同小异,只是个人觉得Code::Blocks没有快捷键调试起来有点麻烦啊。