调试程序的简单说明.
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
难怪很多前辈说调试是一个程序员最基本的技能,其重要性甚至超过学习一门语言。不会调试的程序员就意味着他即使会一门语言,却不能编制出任何好的软件。
我以前接触的程序大多是有比较成形的思路和方法,调试起来出的问题都比较小,最近这个是我自己慢慢摸索调试,接触了很多新的调试方法,并查了很多前辈的总结,受益匪浅,总结以前的和新的收获如下:
VC 调试篇
设置
为了调试一个程序,首先必须使程序中包含调试信息。一般情况下,一个从AppWizard 创建的工程中包含的Debug Configuration 自动包含调试信息,但是是不是Debug 版本并不是程序包含调试信息的决定因素,程序设计者可以在任意的Configuration 中增加调试信息,包括Release 版本。
为了增加调试信息,可以按照下述步骤进行:
∙
打开Project settings 对话框(可以通过快捷键ALT+F7打开,也可以通过IDE 菜单Project/Settings 打开
∙选择C/C++页,Category 中选择general ,则出现一个Debug Info 下拉列表框,可供选择的调试信息方式包括:
命令行 Project settings 说明
无 None 没有调试信息
/Zd Line Numbers Only 目标文件或者可执行文件中只包含全局和导出符号以及代码行信息,不包含符号调试信息
/Z7 C 7.0- Compatible 目标文件或者可执行文件中包含行号和所有符号调试信息,包括变量名及类型,函数及原型等
/Zi Program Database 创建一个程序库(PDB,包括类型信息和符号调试信息。
/ZI Program Database for Edit and Continue 除了前面/Zi 的功能外,这个选项允许对代码进行调试过程中的修改和继续执行。这个选项同时使
#pragma 设置的优化功能无效
∙
选择Link 页,选中复选框"Generate Debug Info",这个选项将使连接器把调试信息写进可执行文件和DLL
∙如果C/C++页中设置了Program Database 以上的选项,则Link
incrementally 可以选择。选中这个选项,将使程序可以在上一次编译的基础上被编译(即增量编译,而不必每次都从头开始编译。调试方法:
1、使用 Assert(原则:尽量简单assert只在debug下生效,release下不会被编译。
2、防御性的编程
3、使用Trace
4、用GetLastError来检测返回值,通过得到错误代码来分析错误原因
5、把错误信息记录到文件中
位置断点(Location Breakpoint
大家最常用的断点是普通的位置断点,在源程序的某一行按F9就设置了一个位置断点。但对于很多问题,这种朴素的断点作用有限。譬如下面这段代码:
void CForDebugDlg::OnOK(
{
for (int i = 0; i < 1000; i++ //A
{
int k = i * 10 - 2; //B
SendTo(k; //C
int tmp = DoSome(i; //D
int j = i / tmp; //E
}
}
执行此函数,程序崩溃于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”。
另外,如果在此编辑框中如果只输入变量名称,则变量发生改变时,断点才会启动。这对检测一个变量何时被修改很方便,特别对一些大程序。
用好位置断点的修饰条件,可以大大方便解决某些问题。
数据断点(Data Breakpoint
软件调试过程中,有时会发现一些数据会莫名其妙的被修改掉(如一些数组的越界写导致覆盖了另外的变量,找出何处代码导致这块内存被更改是一件棘手的事情(如果没有调试器的帮助。恰当运用数据断点可以快速帮你定位何时何处这个数据被修改(最好使用内存来查找,使用变量名的话,IDE不一定能找到。。譬如下面一段程序:
#include "stdafx.h"
#include
int main(int argc, char* argv[]
{
char szName1[10];
char szName2[4];
strcpy(szName1,"shenzhen";
printf("%s\n", szName1; //A
strcpy(szName2,
"vckbase"; //B
printf("%s\n", szName1;