VC条件断点和数据断点

来源:互联网 发布:网络赚钱棋牌游戏 编辑:程序博客网 时间:2024/05/16 12:27

VC高级调试方法-条件及数据断点的设定

(一)位置断点(LocationBreakpoint)

大家最常用的断点是普通的位置断点,在源程序的某一行按F9就设置了一个位置断点。但对于很多问题,这种朴素的断点作用有限。譬如下面这段代码:

void CForDebugDlg::OnOK()

{

for(int i = 0; i < 1000; i++) //A

{

intk = i * 10 - 2; //B

SendTo(k); //C

inttmp = DoSome(i); //D

Trace0("这里要输出的内容”);//在这里可以输出一些有用的信息,你也可以输出I的值,都是可以的

intj = i / tmp; //E

}

}

//其实我们还可以用其他方法调式也是一样的,你可以用TRACE0宏来输出循环中的每一个结果,我们也可以在debug中看见输出的结果,当出现问题时,输出的结果可能就不一样了,我们可以分析一下debug中的结果找出问题的所在

执行此函数,程序崩溃于E行,发现此时tmp为0,假设tmp本不应该为0,怎么这个时候为0呢?所以最好能够跟踪此次循环时DoSome函数是如何运行的,但由于是在循环体内,如果在E行设置断点,可能需要按F5(GO)许多次。这样手要不停的按,很痛苦。使用VC6断点修饰条件就可以轻易解决此问题。步骤如下。
1 Ctrl+B打开断点设置框,如下图:

Figure 1设置高级位置断点
2 然后选择D行所在的断点,然后点击condition按钮,在弹出对话框的最下面一个编辑框中输入一个很大数目,具体视应用而定,这里1000就够了。
3 按F5重新运行程序,程序中断。Ctrl+B打开断点框,发现此断点后跟随一串说明:...487 times remaining。意思是还剩下487次没有执行,那就是说执行到513(1000-487)次时候出错的。因此,我们按步骤2所讲,更改此断点的skip次数,将1000改为513。
4 再次重新运行程序,程序执行了513次循环,然后自动停在断点处。这时,我们就可以仔细查看DoSome是如何返回0的。这样,你就避免了手指的痛苦,节省了时间。
再看位置断点其他修饰条件。如Figure 1所示,在“Enter the expression to be evaluated:”下面,可以输入一些条件,当这些条件满足时,断点才启动。譬如,刚才的程序,我们需要i为100时程序停下来,我们就可以输入在编辑框中输入“i==100”。
另外,如果在此编辑框中如果只输入变量名称,则变量发生改变时,断点才会启动。这对检测一个变量何时被修改很方便,特别对一些大程序。
用好位置断点的修饰条件,可以大大方便解决某些问题。


二) 数据断点(DataBreakpoint)

软件调试过程中,有时会发现一些数据会莫名其妙的被修改掉(如一些数组的越界写导致覆盖了另外的变量),找出何处代码导致这块内存被更改是一件棘手的事情(如果没有调试器的帮助)。恰当运用数据断点可以快速帮你定位何时何处这个数据被修改。譬如下面一段程序:

#include "stdafx.h"

#include <string.h>

int main(int argc, char* argv[])

{

charszName1[10];

charszName2[4];

strcpy(szName1,"shenzhen");

printf("%s\n",szName1); //A

strcpy(szName2,"vckbase"); //B

printf("%s\n",szName1);

printf("%s\n",szName2);

return0;

}

这段程序的输出是

szName1: shenzhen

szName1:ase

szName2:vckbase

首先我给你分析一下为什么会是这样的结果呢!首先你在strcpy(szName1,"shenzhen");这个地方F9设置一个断点,然后F5运行程序,这是程序会断到我们设置的断点,如下图

看到了吧,问题出现的原因就在这里,系统给szName2分配的地址是0x0012ff70这里是4个字节,然后呢,在0x0012ff70后面4个字节处,开始分配szName1这10个字节,也就是在0x0012ff74处开始分配10个字节,

F10单步跟踪,来到printf("%s\n", szName1)这一行,如下图

szName1分配的空间已经附上了值.

F10走到下一个printf("%s\n", szName1) 看下图,

因为szName1 和szName2分配的空间是连续的,所以给szName2赋值超过所容纳的字节时就开始覆盖szName1的内容了,所以说当我们在输出结果的时候就出现我们想不到的结果了,

那么怎么去调试呢,下面是具体的方法

szName1何时被修改呢?因为没有明显的修改szName1代码。我们可以首先在A行设置普通断点,F5运行程序,程序停在A行。然后我们再设置一个数据断点。如下图:

Figure 2 数据断点
F5继续运行,程序停在B行,说明B处代码修改了szName1。B处明明没有修改szName1呀?但调试器指明是这一行,一般不会错,所以还是静下心来看看程序,哦,你发现了:szName2只有4个字节,而strcpy了7个字节,所以覆写了szName1。
数据断点不只是对变量改变有效,还可以设置变量是否等于某个值。譬如,你可以将Figure 2中红圈处改为条件”szName2[0]==''''y''''“,那么当szName2第一个字符为y时断点就会启动。
可以看出,数据断点相对位置断点一个很大的区别是不用明确指明在哪一行代码设置断点。、

 

 

 

FROM:http://www.cnblogs.com/VCdog/archive/2010/05/20/1739871.html

原创粉丝点击