vc常用的调试命令,vc++调试程序
F10:调试到下一句,这里是单步跟踪。
F11:调试到下一句,在函数内部跟进。
Shift F11:跳出当前功能
Ctrl F10:调试到光标位置
F9:设置(取消)断点
Alt F9:高级断点设置
跟踪调试
1.使用快捷键时尽量调试。
2.观察调试信息。
3.高级中断设置
异常调试
重试-取消-调试
函数堆栈,使用变量或调用堆栈窗口
发布调试
1.始终测试您的调试和发布版本。
2.不要删除调试代码,比如使用ASSERT、TRACE等。
3.初始化变量,尤其是全局变量,内存和新内存。
4.删除资源时,请确保删除了与该资源相关的所有语句(主要在resource . h文本中)。
5.用警告级别3或4编译你的代码,确保没有警告,项目-设置-C/C-警告级别(中文版是项目-属性-C/C-常规-警告级别)
6.将_debug改为NDEBUG进行调试,项目-设置-C/C-预处理器定义(中文版是项目-属性-C/C-预处理器-预处理定义)(这里是调试和发布编译的重要区别之一)
7.调试发布中的源代码。项目-设置-C/C-调试信息选择程序数据库(中文版为项目-属性-C/C-通用-调试信息格式-程序数据库为“编辑并继续”),项目-设置-链接选择生成调试信息(中文版为项目-属性-链接器-调试-生成调试信息)
8.浏览代码,特别注意堆栈和指针。
第二,跟踪宏
当选择了调试目标并且afxTraceEnabled变量设置为TRUE时,跟踪宏被激活。但是在该程序的发布版本中,它们被完全禁止。以下是典型的跟踪语句:
…
int nCount=9;
CString strDesc( total );
TRACE(Count=%d,Description=%s\n ,nCount,strDesc);
…
如您所见,TRACE语句的工作方式有点像C语言中的printf语句。跟踪宏参数的数量是可变的,因此非常容易使用。如果看MFC的源代码,根本找不到TRACE宏,只能看到TRACE0,TRACE1,TRACE2,TRACE3宏,它们的参数分别是0,1,2,3。
个人总结:最近看网络编程的时候碰到了TRACE语句。不知道从哪里输出,但是一晚上都没找到。今天,我终于找到了。该方法如下:
1.在MFC中添加跟踪语句。
2.在工具- MFCTRACER中选择“启用跟踪”,然后单击确定
3.进行调试操作,GO(F5)(特别说明:不是执行!之前看不到跟踪内容的原因是不是调试执行,而是!记得,记得,记得)
4.然后,您将在输出的调试窗口中看到跟踪内容,调试执行将自动从构建窗口跳转到调试窗口,您将在那里看到跟踪内容。_
以下是您要寻找的踪迹的详细介绍:
==============================
TRACE对于VC下的程序调试来说是一个非常有用的东西,有类似printf的功能;这个宏只出现在程序的调试版本中,发布时完全消失,从而帮助你在发布时调整和减少代码量。
使用起来非常简单,格式如下:
TRACE( dddddddddd );
TRACE(wewe%d ,333);
TRACE0、TRACE1和TRACE2也存在。分别对应于0、1和2。因素
跟踪信息输出到VC IDE环境的“输出”窗口(该窗口是编译项目错误提示的窗口),但前提是在VC中运行程序的调试版本。
还可以使用DEBUGVIEW捕获跟踪信息。在这种情况下,你不能在VC的IDE环境下运行你的程序,只能单独运行程序的BUILD DEBUG版本。此时,您可以在DEBUGVIEW窗口中看到DEBUGVIE格式的输出。
VC跟踪在中有四种用法:
1,即没有动态参数的输出字符串,类似于C的printf(“输出字符串”);
TRACE2: 2中的字符串可以用一个参数输出,类似于printf(.%d ,变量);
3: TRACE3可以用两个参数输出,就像C(的printf.% d.% f ,变量1,变量2);
TRACE4可以用三个参数输出,比如C(的printf.%d,%d,% d ,变量1,变量2,变量3);
TRACE有点像我们之前在C语言中使用的Printf函数,让程序在运行过程中输出一些调试信息,让我们知道程序的一些状态。但是有一点不同:
TRACE只能在调试时输出,而之前使用的Printf函数在任何情况下都可以输出。像Printf函数一样,TRACE函数可以接受多个参数,例如:
int x=1;
int y=16
float z=32.0
TRACE(这是一个跟踪语句\ n );
TRACE( x的值是%d\n ,x);
TRACE( x=%d和y=%d\n ,x,y);
TRACE( x=%d和y=%x和z=%f\n ,x,y,z);
请注意,跟踪宏仅适用于项目的调试版本,在项目的发布版本中,跟踪宏将被忽略。
三。断言宏
如果您设计了一个需要指向文档对象的指针作为参数的函数,但是您错误地用视图指针调用了这个函数。这个假地址会导致视频数据的破坏。现在,这种类型的问题可以完全避免,只要在函数的开头实现一个ASSERT测试来检测指针是否真的指向一个文档对象。一般来说,程序员通常应该在每个函数的开头使用断言。ASSERT宏将判断表达式。如果表达式为真,执行将继续。否则,程序将显示一条消息并暂停。您可以选择忽略此错误并继续,终止程序或跳转到调试。下面的示例演示如何使用ASSERT宏来验证语句。
void foo(char p,int size)
{
断言(p!=0);//确认指向缓冲区的指针有效
ASSERT((size=100);//确认缓冲区至少有100个字节
//进行foo计算
}
除非设置了DEBUG处理器标志,否则这些语句不会生成任何代码。visual ++只在调试版本中设置这些标志,在发布版本中没有定义。当定义了—DEBUG时,两个断言将生成以下代码:
//ASSERT( p!=0 );
做{
如果(!(p!=0)AfxAssertFailedLine(—文件—,—行—))
AfxDebugBreak();
} while(0);
//ASSERT((size100);
做{
如果(!(size=100)& & AfxAssertFailedLine(—文件—,—行—))
AfxDebugBreak();
} while(0);
Do-while循环将整个断言封装在一个块中,这使得编译器很容易编译。If语句计算表达式,并在结果为零时调用AfxAssertFailedLine()函数。这个函数会弹出一个对话框,有“取消、重试、忽略”三个选项,选择“重试”会返回TRUE。重试将导致调用AfxDebugBreak()函数,从而激活调试器。
AfxAssertFailedLine()是一个未公开的函数,它的作用是显示一个消息框。此函数的源代码驻留在afxasert.cpp中。函数中的-file-and-line-语句是处理器标志,分别指定源文件名和当前行号。
AfxAssertFailedLine()是一个未公开的函数,它的作用是显示一个消息框。此函数的源代码驻留在afxasert.cpp中。函数中的-file-and-line-语句是处理器标志,分别指定源文件名和当前行号。
第四,验证宏观
因为断言只能在程序的调试版本中起作用,所以不能在表达式中包含赋值语句、增加语句(++)或减少语句(-),因为这些语句实际上改变了数据。但有时你可能想验证一个动态表达式,并使用赋值语句。那么是时候用VERIFY宏替换ASSERT了。例如:
voidfoo(char p,int size)
{
char q;
验证(q=p);
ASSERT((size100);
//进行foo计算
//进行foo计算
}
在调试模式下,断言和验证是一回事,但是在发布模式下,验证宏仍然测试表达式,断言没有任何作用。可以说在发布模式下,ASSERT语句已经被删除了。
请注意,如果您在ASSERT语句中错误地使用了活动表达式,编译器将会忽略它而不会发出警告。在Release模式下,表达式会被静默删除,导致程序的错误操作。因为程序的发布版本通常不包含调试信息,这样的错误将很难被发现。
动词(verb的缩写)VC高级调试方法-设置条件和数据断点
(a)位置断点(LocationBreakpoint)
最常用的断点是常用位置断点,在源程序的一行按F9设置一个位置断点。但是对于很多问题来说,这个简单的断点作用有限。例如,下面的代码:
void CForDebugDlg:OnOK()
{
for(int I=0;i 1000i ) //A
{
intk=I * 10-2;//B
send to(k);//C
int tmp=do some(I);//D
Trace0(这里输出什么);//这里可以输出一些有用的信息,也可以输出I的值,两者都可以。
intj=I/tmp;//E
}
}
//其实我们也可以用别的方法,模式也是一样的。可以使用TRACE0宏输出循环中的每一个结果,我们也可以在debug中看到输出结果。出错时,输出结果可能会有所不同。我们可以在调试中分析结果,找出问题所在。
当执行这个函数时,程序在E行崩溃,此时发现tmp为0。假设tmp不应该是0,这个时候怎么会是0呢?所以最好跟踪DoSome函数在这个循环中是如何运行的,但是由于它在循环内部,如果在E行设置断点,可能需要多次按F5(GO)。一直这样按手很痛苦。通过用VC6断点修改条件,可以很容易地解决这个问题。步骤如下。
Ctrl B打开断点设置框,如下图所示:
图1设置了高级位置断点
2然后选择D行所在的断点,然后点击条件按钮,在弹出的对话框底部的编辑框中输入一个大数。视应用而定,这里1000就够了。
按F5重新运行程序,程序中断。B Ctrl打开断点框,找到这个断点后,后面跟着一串指令:还剩487次。意味着还剩下487次要执行,也就是说执行到513 (1000-487)次就有错误了。因此,我们将这个断点的跳转号从1000更改为513,如步骤2中所述。
4再次运行程序,程序执行513个循环,然后自动停在断点处。此时,我们可以仔细看看DoSome是如何返回0的。这样可以避免手指的疼痛,节省时间。
再看位置断点的其他修改条件。如图1所示,在“输入要计算的表达式:”下,可以输入一些条件。当满足这些条件时,断点将开始。比如刚才的程序,我们需要程序在I为100时停止,那么我们可以在编辑框中输入“i==100”。
此外,如果仅在此编辑框中输入变量名,则断点将仅在变量更改时启动。这便于检测变量何时被修改,尤其是对于一些大型程序。
利用好位置断点的修改条件,可以大大解决一些问题。
(2)数据断点(数据断点)
在软件调试的过程中,有时候会发现有些数据会被莫名其妙的修改(比如有些数组写越界了,导致覆盖了其他变量)。找出代码导致内存改变的地方是一件棘手的事情(没有调试器的帮助)。正确使用数据断点可以快速帮助您定位数据被修改的时间和位置。例如,下面的程序:
#include stdafx.h
#包含字符串. h
int main(int argc,char* argv[])
{
charszname 1[10];
charszname 2[4];
strcpy(szName1,深圳);
printf(%s\n ,SZ name 1);//A
strcpy(szName2, vck base );//B
printf(%s\n ,SZ name 1);
printf(%s\n ,SZ name 2);
return0
}
这个程序的输出是
深圳名称1:深圳
szName1:ase
szName2:vckbase
首先我给大家分析一下为什么会是这样的结果!首先你在strcpy(szName1,深圳);这个地方F9设置了一个断点,然后F5运行程序,也就是说程序会中断到我们设置的断点,如下图所示。
看,这就是问题的原因。系统分配给szName2的地址是0x0012ff70,这里是4个字节。然后,在0x0012ff70之后的4个字节,分配szName1的10个字节,即在0x0012ff74,
F10单步跟踪,来行printf(%s\n ,szName1),如下图所示。
szName1分配的空间已经附加了一个值。
F10转到下一个printf(%s\n ,szName1),并查看下图。
因为szName1和szName2分配的空间是连续的,所以当赋给szName2的值超过它所包含的字节数时,szName1的内容就开始被覆盖,所以当我们输出结果时,就出现了意想不到的结果。
那么如何调试呢?下面是具体的方法。
szName1是什么时候修改的?因为szName1代码没有明显的修改。我们可以先在A行设置一个公共断点,F5运行程序,程序停在A行,然后我们设置一个数据断点。如下图:
图2数据断点
F5继续运行,程序停在B行,表示B处的代码修改了szName1。为什么没有在B位修改szName1?但是调试器指示这一行,一般是正确的,还是静下心来看看程序比较好。哦,你发现szName2只有4个字节,而strcpy有7个字节,所以覆盖了szName1。
数据断点不仅对变量变化有效,还可以设置变量是否等于某个值。例如,您可以将图2中的红色圆圈更改为条件“szName2 [0]== y ”,那么断点将在szName2的第一个字符为y时开始。
可以看出,数据断点和断点的一个很大的区别是,你不用指定在哪一行代码上设置断点。
(3)其他
1在调用堆栈窗口设置断点,选择一个函数,按F9设置断点。这样就可以从深层的函数调用中快速返回到需要的函数。
2设置下一条语句命令(该命令在调试期间右击debug)
该命令的功能是将程序的指令指针(EIP)指向不同的代码行。比如你正在调试上面的代码,它运行在A行,但是你不想运行B行和c行,这时候你可以右击D行,然后“设置下一条语句”。调试器不会执行B行和c行,只要是在同一个函数中,这个指令可以在跳转之前或之后任意执行。灵活使用该功能可以节省大量的调试时间。
3观察窗
监视窗口支持丰富的数据格式化功能。如果输入0x65,u,右栏将显示101。
显示实时windows API调用的错误:在左栏输入@err,hr。
调用"监视"窗口中的函数。作为提醒,在调用该函数后,请立即清除“监视”窗口中的该函数,否则,调试器将在单步调试期间的每一步都调用该函数。
4消息断点不是很实用。基本上可以用前面提到的断点来代替。
六个。VC调试环境设置
为了调试程序,必须首先在程序中包含调试信息。通常从AppWizard创建的项目中包含的调试配置会自动包含调试信息,但是否是调试版本并不是程序包含调试信息的决定性因素。程序员可以在任何配置中添加调试信息,包括发布版本。
为了添加调试信息,您可以遵循以下步骤:
打开“项目设置”对话框(可通过快捷键ALT F7或IDE菜单“项目/设置”打开)
选择C/C页,在类别中选择常规,将出现调试信息下拉列表框。调试信息选项包括:
命令行项目设置描述
无无没有调试信息
/Zd Line Numbers Only目标文件或可执行文件仅包含全局和导出的符号和代码行信息,但不包含符号调试信息。
/Z7 C7.0兼容的目标文件或可执行文件包含所有符号的行号和调试信息,包括变量名和类型、函数和原型等。
/Zi程序数据库创建一个程序库(PDB),包括类型信息和符号调试信息。
/ZI程序数据库
除了前面的/Zi,Edit and Continue功能之外,该选项还允许在调试期间修改和继续执行代码。此选项还会使#pragma设置的优化函数无效。
选择链接页面并选中复选框“Generate DebugInfo”,这将使连接器将调试信息写入可执行文件和DLL。
如果在C/C页面中设置了程序数据库上方的选项,则可以增量选择链接。选择此选项将使程序能够在上次编译的基础上进行编译(即增量编译),而不必每次都从头编译。
郭于是乎又做收集和整理。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。