【C\C++语言入门篇】-- 调试基础
通过前面两篇,相信大家已经基本了解了我们的研究思路。既然是研究,那么必须的研究工具就得熟练掌握了。这里我所指的研究工具就是VC,我所使用的VC版本是2005。本文也将根据VC2005进行探讨。可能很多朋友或者初学者还是使用的VC6.0。在这里本人不推荐使用VC6.0。原因很简单,VC6.0已经过时了,后面的版本比VC6.0更强大方便。可能也是因为众多经典的程序设计书籍使用的都是VC6.0。有的朋友可能不是很清楚VC6.0和VS系列到底有什么关系,那么简单的说,VS系列就是集成VC功能等诸多比如C#、VB、.NET等语言为一体的强大IDE环境。我们当然毫不犹豫的选择强大。好了,切入正题!
今天我们探讨的是VC自带的强大调试器,在众多调试器中,VC的调试器也是相当成熟的调试器之一了。我们程序员绝对离不开他。在我们初写程序的时候,好不容易写完了并编译通过了上百行代码的一个程序,激动难以言表只是按下F5运行,结果得不到我们的想要的结果。激动欣喜顿时变成沮丧苦恼。我该怎么办?怎么才能排查我哪里错了呢?一行一行看代码?这时就需要用到调试器了。下面我们先列举几条,方便理清思路也方便大家总结归纳。
1.简单断点。
2.单步调试(步入,步过)。
3.监视窗口。
4.内存窗口。
5.堆栈窗口。
6.断点窗口。
7.局部变量窗口。
暂时列举上面几条,更多比如数据断点,寄存器窗口等其它调试方法及窗口再后面有时间我们再一一介绍。那下面我们就一一介绍上面的7点。
简单断点 通俗的讲断点(这里只是简单的F9断点及双击某行下断)就是能够让程序运行到断点位置时能够停下来,至于为什么能够停下来这个我们就先别管了。只需要知道断点就是为了程序运行到断点的时候停下来,这时方便我们观察一些数据。检查正确性。打断点可以将光标定位到某行,然后按下F9便设置了断点。同样可以在某行的最前面边框上双击打下断点。断点打下后,在此行最前面会有一个红色的圆点。如图:
单步调试这条是比较基本的,所谓单步,就是一步一步的走,一步执行一条语句。当然如果你把多条语句写到一行或者用宏定义。那么这样将对你单步调试带来困扰。这样你非得要看具体过程可以试试反汇编跟踪。启动单步调试可以是F10。如果用F10你可以不下断点,程序会自动在main函数入口处断下来。断下来后,我们就有两种选择了。一、继续F10就是一次一条语句。如果碰到函数调用,并不会单步进入函数中断。直接执行完整个函数后断在函数调用的下一条语句。因此称为步过。二、F11进行单步调试,此种方式与F10不同在于碰到函数调用会进入函数中断。此方法适合步步跟踪。因此称为步入。这里需要说明的是,这两种方式一般是结合着使用。提示:我们在单步的同时,比如要观察某个变量的值,可以将鼠标指向此变量。编译器会自动显示当前变量的值。同时在单步的过程中执行到某行时,前面会有个黄色的箭头。很清晰明了。如图:
这里的count很清晰的可以看到值。只需要指向它。这里显示的10进制,我们也可以显示16进制。可以点击:
就会显示0x?????字样了。监视窗口这是一个非常重要的窗口,所谓监视就是偷窥某个变量的值、函数返回值、计算一些表达式等。监视窗口也有4个,一般我们初学者只需用1个,启动监视1可以用ALT + 3快捷键。
问题一:其它监视窗口的快捷键是什么?
同样是上面图中的程序,我们要监视count变量的值。如图:
这里的名称可以直接输入,也可以直接选中count变量,然后左键拖动到监视窗口里。就可以显示变量的当前值了。要显示十六进制也可以在点击前面说的“十六进制”按钮。也可以右键监视窗口选择十六进制显示。是不是很直观呢。同样也可以看count变量的地址哟。这里的地址也就是在内存里面存放的地址,如图:
unsigned int* pCount = &count; pCount指针的值也就是这个地址。从上面的监视窗口里,大家应该可以感受到VS的强大了吧。提示:双击监视窗口里面的各个“名称”或“值”可以改变这些值的哟。这里再提一个问题:
问题二:怎么只观察name变量的某一个元素的值?尽量写出多种方式。
内存窗口这是一个比较重要的窗口,我们以前很疑惑某个数据或者字符串在内存中是怎么存储的,今天我们就可以通过内存窗口进行观察。内存窗口就是显示的数据在进程内存中具体的存储位置及方式。启动内存窗口在断点断下来后可以用快捷键:CTRL+ALT+M+(1,2,3,4)因为一共有4个内存窗口,方便我们多用。也可以在调试断点断下来的时候点击菜单栏的调试--->窗口---->内存---->内存1,2,3,4来启动。内存窗口经常结合者监视窗口一起用。为什么,先如图:
上面我在地址后面的编辑框里面输入的是count的地址。看监视窗口的&count或者pCount后面的值就是0x0012ff5c。所以这里也说明这两个是等同的。我们惊喜的发现选中的地方跟0x80000000很像那呢?内存窗口里面可以右键选择1字节整数,2字节整数,4字节整数等。我这里选择的是1字节整数。就是一个字节一个字节的显示。这里如果是四字节整数的话就是:
哈哈,是不是神奇的发现4字节结合在一起就是0x80000000。那
问题三:为什么上面的内存窗口的00在前面而80在后面呢?(提示,0x80000000为8个字符宽式因为00表示一个字节,总共4字节)
这里假如要在内存窗口里面查看pCount所指向的内存的值,就可以直接选中pCount指针变量,然后左键拖入内存窗口的地址编辑框(注意,这里不能直接把count变量给拖下来,这样拖下来的话编辑框里就是count的值0x80000000,看的就是这个地址下面的值了,至于拖pCount能行,很明显是因为他是指针,它的值就是count变量的地址)。也就能查看count变量所存储的位置及值了。其他更巧妙的用法大家自己摸索,熟悉了就能总结出用法了。提示:光标定位到某个地址的内存,可以修改这个内存的值哟。只读或保护内存除外。
堆栈窗口此窗口就是方便我们看函数调用的。可以使用 ALT+7启动显示出来。当然也是在调试断下来后可以使用。当我们的函数调用一层又一层比如递归等,或者有虚函数时等堆栈窗口可以直接看整个调用流程,排错起来就方便多了。如图:
代码依然断在监视窗口的那段代码截图那里,上面的堆栈窗口能够清晰的看到调用层次。当前是在main函数里面,通过箭头可以看出来。这里也可以看出来main函数之前还有函数调用main函数。是不是有清晰了一大步?我们可以双击某一行查看调用的地方的代码。我点击> TestC.exe!__tmainCRTStartup() 行597 + 0x19 字节这行后如图:
嘿嘿,很清晰的看到在这里调用的吧~~。好累,喝口水。继续。
断点窗口此窗口用于显示当前你打下的所有断点,我们可以双击某一行定位到断点的位置。我们想要不删除这个断点而只需要暂时不起作用就可以去掉前面选择框里面的勾。启动此窗口可以使用ALT + F9快捷键。如图:
局部变量窗口此窗口用于显示当前断下来后函数内所有局部变量的值,跟监视窗口类似。不过固定为局部变量的值。不能编辑。启动此窗口可以使用ALT + 4快捷键。
到这里就基本介绍完了,还有更多高级调试不便在本文讲述,以后我们在探讨。在这里我们需要记得几点:
1.这些窗口在调试过程中都是结合者使用的。
2.调试的时候需要有耐心,多思考什么地方最容易出错,针对性的检查排除。有时候需要写一些测试代码方便跟踪调试。
3.可以根据出错结果的现象或信息,针对性的下断。技巧要总结。
好了。终于大功告成了。有什么地方有错误还望大家提出来,希望本文对一些朋友有帮助。大牛略过!