VC调试技术
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
VC调试技术
程序出错的类型大致可以分为两种,语法错误和逻辑错误。
语法错误可以通过编译器的出错信息得到纠正。
然而逻辑错误则不能,所以各大IDE(集成开发环境)中都提供了debug功能,用来分析和排除程序中的逻辑错误,排除逻辑错误的过程又称调试(或debug),下面谨以VC++6.0的调试环境做介绍。
常用的调试命令主要有:
step into 命令快捷键:F11
单步执行每条语句,在遇到函数的时候,系统将进入函数,单步执行其中的语句。
step over 命令快捷键:F10
单步执行每条语句,但在遇到函数时候,系统将把函数当作“一条语句”来执行,自动执行其中的内容,而不进入函数内部单步执行。
run to cursor 命令快捷键:Ctrl+F10
系统将自动执行到用户光标所指的语句前。
(这个功能很有用,可以将精力集中到有问题的地方,从而节省调试时间)
Go 命令快捷键:F5
系统将编译,连接,自动运行程序,但是会在程序设置了断点(breakpoint)处停下。
BuildExcute 命令快捷键:Ctrl+F5
系统将编译,连接,运行编译好的程序代码,因此不会在断点处停留,但是在程序执行结束之后,系统会给一个Pause,以方便用户观察输出结果。
Stop debug命令快捷键:Shift+F5
本命令是用来终止动态调试过程的。
动态调试的主要方法——watch(监视变量)
在程序编译通过以后,当使用了step into,step over,run to cursor, go命令使系统在程序执行的过程中停下之后,系统就会进入调试状态。
调试过程中,你的程序执行窗口会调到后台,而系统窗口中会显示你的程序,其中的黄色箭头指向的是系统下一步将要执行的语句。
而系统窗口下面的那个监视窗口就是我们将要介绍的重点.
watch窗口被左右分成了两个部分,左面的那部分我们姑且称之为“自动监视区”(即variable窗口),而右面的我们称之为“手动监视区”。
(即watch窗口)
自动监视区是系统自动跟踪的变量名。
系统默认显示auto标签,那是显示在上一步执行过程中,程序中发生改变的变量。
locals标签跟踪的是某一个函数中的所有变量。
上面的find sourse组合框中指示的是当前在locals标签下在跟踪的变量是属于哪一个函数的。
说明:当find sourse组合框中的内容变成灰色时,说明系统正在运行程序,或者等待输入端的数据(通常会是这个情况),此时应当注意程序执行窗口中的内容。
然而通常仅仅只有自动监视区所监视的变量是不够的,有时我们需要自己定义一些需要跟踪的变量——这个时候我们就要在手动监视区中输入变量名(也可以是系统认为合法的表达式)来跟踪我们需要的值。
注意:当用户定义了一个指向数组的watch之后,在变量的左边会出现一个小的'+'号,表示这个数组可以“展开”——显示其中每一个下标所指示的内容,这与其他高级语言的IDE有些不同。
值得一提的是VC++的一个人性化设置:在用户定义的变量很多时,往往需要通过滚屏才能看到所
有的变量——VC++在手动监视区中设定了4个标签以方便用户的使用,在这四个标签的功能是一样的!
断点的设置与一些基本的调试技巧。
断点(breakpoint)是指在调试过程中,只要运行到断点处,系统就会自动停下(除非是使用bulidexcute命令,但那是在执行编译好的代码,在严格意义上说,这不能算是一个调试命令),通常和go命令和step over命令配合在一起使用。
设置断点的方法:在程序代码中,移动到需要设置断点的那一行上,按F9键,你可以看到代码行的左端出现了一个红色的圆点——那是VC++中断点的标志,以后程序在调试过程中,每次执行到这里,都会停下,方便用户观察watch中的内容。
去除断点的命令与设置断点的命令相同:在已设置断点的地方,再按一次F9键,左端的红色圆点就消失,断点被去除了。
有的时候,我们并不是不需要断点,而是“暂时”不需要它,这时可以在已设置断点的地方,按Ctrl+F9键,你可以看到原本实心的圆点变成了一个空心的圆圈——断点暂时失效了。
恢复断点功能也是按Ctrl+F9。
这个功能在程序很长,需要很多断点的时候尤其有用。
条件断点技术——其实就是在一些分支语句内部设置断点,这个技术很实用,尤其在程序的某个分支部分发生问题的时候。
关于断点设置在哪里。
这可以说是因人而异,而且是一个相当有艺术性的内容,我不想多说什么,但是有一个基本的原则就是,不要连续设置断点,所谓断点,也可以说是“段”点,在需要连续观察的地方,应当使用step over或者step into命令。
好了,调试命令基本上就是这些,下面我想谈谈我个人在调试过程中的一些心得和体会:1.动态调试不是万能的。
虽然动态调试能解决几乎所有的非算法性的问题,但是动态调试要消耗大量的时间这点也是无庸质疑的——而且会扰乱编程者的思路。
其实相当多的错误往往只是因为键盘按错(“手误”)导致的。
这种错误在动态调试中很难发现,所以对于每一个程序,在要开始进行调试前,都应当再整理一遍思路,仔细地通读一遍程序,用所谓的“静态查错”的方法先将一些显而易见的低级错误先解决掉,同时也可以确定调试的重点。
这样做可以大大缩短调试时间,同时能使自己更容易发现一些思路方面的错误。
2.调试时思路要跟着程序转。
说白了就是要集中精力于正在调试的语句段和正在变化的变量上。
3.模块化能有效缩短调试时间。
其实模块化不仅仅能有效的缩短开发时间,更能有效的缩短调试时间。
首先,模块化使得我们够方便的使用step over命令,而减少断点的设置。
其次,程序出错的地方往往就是在几个关键点上,使用了模块化设计思路以后,我们就可以集中精力在那些关键点上,省去了不必要的单步调试。
当然,能面向对象就更好了。
4.多用断点和run to cursor命令,减少单步调试的使用——那样太费时间了。
5.调试不要破坏程序的原本结构。
许多人喜欢在调试过程中输出一些中间变量的值,认为这样做比较直观——当然,这也是一个很重要的手段,尤其在反复递归和循环嵌套的时候。
不过我不推荐在非递归的程序中使用这种方法。
这种方法最大的问题就是破坏了程序原本的结构和逻辑,除非你在原本程序设计时就想到这一点。
这点在程序很长或者思路很复杂时尤为明显。
否则为什么所有的编译模式的程序语言都不约而同的提供了watch这一手段?解释模式的程序语言?那是没有办法……
6.遇到bug时不要急于修改程序。
也就是不要乱打补丁。
道理和第5条一样,要先仔细分析,然后在决定是否要修改——总之,要冷静。
尤其是删除程序段的时候,我建议先把认为不需要的程序段先注释掉。
等到调试成功后再删不迟。
VC++6.0调试工具简介
一、启动Debug工具
在主菜单Build中,有一个Start Debug子菜单,包含了以下4个菜单:
●Go:从当前语句开始执行程序直到遇到断点或遇到程序结束。
●Step Into:单步执行程序;在遇到函数调用时,进入函数内部并从子函数头开始单
步执行。
●Run to Cursor:调试运行程序时,使程序运行到光标所在的行时停止,事实上,这
相当于设置一个临时断点。
●Attach to Process:调试过程中直接进入到正在运行的进程中。
二、Debug菜单
启动调试器后,Debug菜单将取代Build菜单出现在菜单栏中,Debug菜单中含有
调试过程经常要用到的命令菜单项。
●Go:用于在调试过程中,从当前语句启动或继续运行程序。
执行时,程序会一直
正常运行,直到到达断点处停止。
这样,在调试过程中,就可以越过某些已知正确
或不感兴趣的程序段,从而提高调试速度。
●Restart:调试过程中,我们经常会进行一种循环操作,首先找到一条错误的语句,
接着对其做某些修改,然后再从头开始对程序进行调试执行,从而确定刚刚修改的
语句是否按预期的结果执行。
此时,就可以使用Restart菜单项。
选择该菜单项,
系统重新编译程序并放弃当前的所有值。
●Stop Debugging:中断调试过程,返回正常的编辑状态。
●Breaks:在当前位置暂停程序运行。
●Apply Code Change:调试过程中,将所修改的代码加入到源文件中。
●Step Into:调试过程中单步执行程序,而且当程序执行到某一函数调用时,进入函
数内部,从头开始单步执行。
●Step Over:调试过程中单步执行程序,但当程序执行到某一函数调用时,不进入函
数内部,直接执行完该函数,接着再执行调用函数语句后的语句。
●Step Out:该菜单项和Step Info配合使用,当执行Step Into语句进入函数内部时,
若发现并不需要对该函数的内部进行单步执行,就可以使用Step Out菜单项,使程
序直接向下执行,直到从该函数内部返回,在该函数调用语句后面的语句处停止。
●Run to Cursor:调试运行程序时,使程序运行到光标所在的行时停止,事实上,这
相当于设置一个临时断点。
●Step Info Specific Function:单步执行选定的函数。
●Exceptions:显示与当前程序有关的所有异常,可以控制调试器如何处理系统异常
和用户自定义异常。
●Threads:显示调试过程中的所有线程,可以挂起或恢复线程并设置焦点。
●Modules:显示当前装入的所有模块。
●Show Next Statement:显示即将执行的代码行。
●Quick Watch:查看及修改变量和表达式或将变量和表达式添加到观察窗口。
三、如何利用断点
如果只对程序中的某一段代码进行调试,而对于在它之前的那些程序段并不感兴趣,此时就可以设置断点了。
设置断点有三种方法:
●将光标移动到需要调试的程序代码行,单击鼠标右键选择Insert/Remove
Breakpoints菜单项。
●将光标移动到需要调试的程序代码行,单击键盘上的F9键。
●将光标移动到需要调试的程序代码行,单击主菜单中的Edit菜单,选择Breakpoints
菜单项,在弹出的对话框中即可设置断点的位置和一些其他的属性。
设定断点后在代码行的前面出现了一个棕色的圆,表明此代码行处有一个断点。
如果调试程序时,有一个断点暂时不需要了,可在此断点处单击鼠标右键,在弹出的快捷菜单中选择Disable Breakpoint项,使得断点无效。
此时断点变成了一个空心的圆,但并未删除此断点。
当需要时在断点处单击鼠标右键,选择Enable Breakpoint菜单项,可恢复断点。
设置完断点后,若调试器尚未启动,单击Debug菜单中Start Debug子菜单中的Go 菜单项,或单击Build Mini Bar工具栏中的Go按钮,或直接按F5键,即可运行程序到所遇到的第一个断点处。
若调试器已经启动,单击Debug菜单中的Go菜单项,或单击Build Mini Bar工具栏中的Go按钮,或直接按F5键,即可运行程序到所遇到的第一个断点处。
重复此操作,可以运行程序到下一个断点。
当调试程序完成或不需要已有的断点时,在断点处单击鼠标右键,在弹出的快捷菜单
中选择Remove Breakpoint项,删除断点。