开发环境:VC6.0
调试技术,对于一个程序员来说,其重要性不言而喻。为此,在此做一个简单的总结。
在Console编程的时候,我们可以使用printf()函数来方便的调试我们的程序。但是在Windows编程中,调试就变得复杂了,尤其是MFC编程。在Windows编程中,我们可以借助一些专门为调试而准备的宏来达到我们的目的。此外,设置断点也是一个非常重要的方法。
一、调试宏
1、TRACE——引自参考资料[2]:VC中的trace
VC中TRACE的用法有以下四种:
a. TRACE ,就是不带动态参数输出字符串, 类似C的printf("输出字符串");
b. TRACE 中的字符串可以带一个参数输出 , 类似C的printf("...%d",变量);
c. TRACE 可以带两个参数输出,类似C的printf("...%d...%f",变量1,变量2);
d. TRACE 可以带三个参数输出,类似C的printf("...%d,%d,%d",变量1,变量2,变量3);
TRACE 宏有点象我们以前在C语言中用的Printf函数,使程序在运行过程中输出一些调试信息,使我们能了解程序的一些状态。但有一点不同的是: TRACE 宏只有在调试状态下才有所输出,而以前用的Printf 函数在任何情况下都有输出。
TRACE信息还可以使用DEBUGVIEW来捕获到。这种情况下,你不能在VC的IDE环境中运行你的程序,而将BUILD好的DEBUG版本的程序单独运行,这个时候可以在DEBUGVIEW的窗口看到DEBUGVIEw格式的输出了。
除了TRACE,类似的还有:TRACE0,TRACE1,TRACE2。。。分别对应0,1,2。。个参数。
实例1:——自编
在VC6.0中创建一个新的MFC AppWizard(exe)工程,在*Doc类中添加成员变量int int_for_debug,并且在其构造函数中对其初始化为1234。在*View的OnDraw()中添加TRACE,如下图所示。
图1 OnDraw()中添加TRACE()
然后在菜单栏中选择调试(F5),则在调试窗口中可以看到相应的输出信息,如下图所示。
图2 TRACE调试信息
2、ASSERT
用法:ASSERT(expression)
解析:如果expression为真,则继续执行下面的程序;否则,暂停执行,并且弹出一个提示框。
实例2:
在VC6.0中创建一个新的MFC AppWizard(exe)工程,在*Doc类中添加成员变量int int_for_debug,并且在其构造函数中对其初始化为1234。在*View的OnDraw()中添加ASSERT,如下图所示。
图3 添加ASSERT
然后在菜单栏中选择调试(F5),则会弹出下图所示的对话框。
图 4 ASSERT Failed!
在图4的红色圈内含有ASSERT语句的位置信息。
选择“忽略”,则可以继续执行往后的代码;如果选择“中止”,这停止程序的运行,在输出栏中可以看到这种情况下的退出代码是3。如下图所示。
图5 “中止”的结果
此外,类是的还有:ASSERT_VALID、ASSERT_KINDOF等。
ASSERT_VALID使用说明:
ASSERT_VALID(CObject派生类对象指针)
ASSERT_VALID宏通过调用重载的AssertValid函数来确定指向CObject派生类对象的指针是否有效。无论你什么时候从CObject派生类中得到一个对象,在对这个对象做任何操作之前都应该调用ASSERT_VALID宏。例如图1中使用ASSERT_VALID对pDC进行检查。如果有误,其提示方式同图4。
3、VERIFY——引自参考资料[3]:VC++宏——VERIFY
C++中的定义:
#define VERIFY(exp) ASSERT(exp) 如果exp的值为真,继续执行;否则中止。
在VC MFC中VERIFY有另一个意思,其是一个判断的宏,MSDN中解释如下:
In the debug version of MFC, the VERIFY macro evaluates its argument. If the result is 0, the macro prints a diagnostic message and halts the program. If the condition is nonzero, it does nothing.
实例3:
在OnDraw()中添加VERIFY,如下图所示。
图5 添加VERIFY
然后在菜单栏中选择调试(F5),则会弹出对话框和图4是一样的!
二、调试函数
1、OutputDebugString()
使用这个函数,可以达到和TRACE一样的效果,如下所示。其输出效果如图7所示。
图6 添加OutputDebugString()函数
图7 添加OutputDebugString()输出信息
三、断点设置
VC6.0支持的断点类型有3种:位置断点、条件断点和xx断点。
1、位置断点
大家最常用的断点是普通的位置断点,在源程序的某一行按F9就设置了一个位置断点。或者在需要设置断点的行单击右键,将会弹出一个快捷菜单,选择"Insert/Remove Breakpoint"即可。添加完后,在对应的行左边有个红色的圆圈标记,如下图所示。
图8 添加位置断点
2、条件断点
添加位置断点比较简单,但是有时候并不能满足要求,这时可以考虑条件断点。
首先,还是要添加一个位置断点,然后Ctrl+B,这时会弹出如下界面。
图9 Ctrl + B 弹出的Breakpoints对话框
在图7左上角默认选中的是Location选项,“分隔符在”下面的输入框为空白,而“条件...”按钮是灰色的状态,表示不可用。左下角的“断点”一栏中可以看到刚才添加的位置断点,选中它,这时“分隔符在”下面的输入框将会填充断点的位置信息,而且“条件...”按钮也变的可用了。如下图
图10 选中断点后
点击“条件...”按钮,为断点设置条件,如下图所示。
图11 断点条件设置
“回车表达式设值”下面,可以输入变量,也可以输入条件。当输入的是变量时,变量改变时断点生效,如图12所示。由图12可见,这时候左下角最后一栏“Enter the number of times to skip before stopping”变成灰色,表示不可用。即变量和次数是不可以配合使用的。执行调试,结果如图11所示。
图12 回车表达式值为变量时(图中的“分隔”就是“断点”的意思!)
图13 使用条件断点,且表达式为变量时
当输入的是条件时,条件满足时断点生效,如图12所示。由图14可见,“Enter the number of times to skip before stopping”这时也变得可用了。也即是说,条件和次数可以配合使用。这时需要注意的是,如图14的设置表示“满足i==5条件100 次,才启用断点”!如果想条件满足就启动断点,应将“Enter the number of times to skip before stopping”设为0或者留空。断点生效时,如图15所示。注意红色圈着的地方和图13是不一样的!
图14 条件断点,且表达式为条件时
图15 使用条件断点,且表达式为条件时
3、数据断点
在图8中可见,左上角还有Data一个选项,它就是设置数据断点的地方。选中它,如图16所示。
图16 数据断点设置
在“回车表达式被看作”下面,可以输入变量,也可以以输入条件(和图14一样!)。需要注意的是,由于变量有全局的,也有局部的。因此,仅仅输入一个变量,还不能达到启动断点的目的。通常的做法是:首先使用位置断点,将程序执行到需要监控变量的位置,然后取消位置断点。Ctrl + B调出数据短点的设置框,输入需要监控的变量!如图17所示。当输入的是变量,断点生效的效果如图18所示;至于“回车表达式”为条件的情况,和图14差不多,不再赘述。
图17 数据断点之变量
图18 图15设置的对应断点效果图
参考资料
[1]vc调试方法大全
[2]trace_百度百科
[3]verify_百度百科
[4]MFC调试技术
[5]VC输出调试信息