您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息

vc++ 调试技巧整理

2024/4/29 20:53:02发布5次查看
vc调试技巧收集整理 调试是一个程序员最基本的技能,其重要性甚至超过学习一门语言。不会调试的程序员就意味着他即使会一门语言,却不能编制出任何好的软件。 这里我简要的根据自己的经验列出调试中比较常用的技巧,希望对大家有用。本文约定,在选择菜单时

vc调试技巧收集整理 
      调试是一个程序员最基本的技能,其重要性甚至超过学习一门语言。不会调试的程序员就意味着他即使会一门语言,却不能编制出任何好的软件。
      这里我简要的根据自己的经验列出调试中比较常用的技巧,希望对大家有用。本文约定,在选择菜单时,通过/表示分级菜单,例如file/open表示顶级菜单file的子菜单open。
1 设置
      为了调试一个程序,首先必须使程序中包含调试信息。一般情况下,一个从appwizard创建的工程中包含的debug   configuration自动包含调试信息,但是是不是debug版本并不是程序包含调试信息的决定因素,程序设计者可以在任意的configuration中增加调试信息,包括release版本。
      为了增加调试信息,可以按照下述步骤进行:
a 打开project settings对话框(可以通过快捷键alt+f7打开,也可以通过ide菜单project/settings打开)      
      b 选择c/c++页,category中选择general ,则出现一个debug info下拉列表框,可供选择的调试信息方式包括: 
      none:
      没有调试信息 
      line numbers only:
      目标文件或者可执行文件中只包含全局和导出符号以及代码行信息,不包含符号调试信息 
      c7 compatible: 
      目标文件或者可执行文件中包含行号和所有符号调试信息,包括变量名及类型.函数及原型 等 
      program database: 
      创建一个程序库(pdb),包括类型信息和符号调试信息。 
      program database for edit and continue: 
      除了上面的功能外,这个选项允许对代码进行调试过程中的修改和继续执行。
      这个选项同时使#pragma设置的优化功能无效
c 选择link页,选中复选框generate debug info,这个选项将使连接器把调试信息写进可执行文件和dll 
      .如果c/c++页中设置了program database以上的选项,则link  incrementally可以选择。选中这个选项,将使程序可以在上一次编译的基础上被编译(即增量编译),而不必每次都从头开始编译。
2 断点
      断点是调试器设置的一个代码位置。当程序运行到断点时,程序中断执行,回到调试器。断点是最常用的技巧。调试时,只有设置了断点并使程序回到调试器,才能对程序进行在线调试。     
      设置断点:可以通过下述方法设置一个断点。首先把光标移动到需要设置断点的代码行上,然后 
      按f9快捷键 
      弹出breakpoints对话框,方法是按快捷键ctrl+b或alt+f9,或者通过菜单edit/breakpoints打开。打开后点击break 
      at编辑框的右侧的箭头,选择 合适的位置信息。一般情况下,直接选择line 
      xxx就足够了,如果想设置不是当前位置的断点,可以选择advanced,然后填写函数、行号和可执行文件信息。 
      去掉断点:把光标移动到给定断点所在的行,再次按f9就可以取消断点。同前面所述,打开breakpoints对话框后,也可以按照界面提示去掉断点。     
      条件断点:可以为断点设置一个条件,这样的断点称为条件断点。对于新加的断点,可以单击conditions按钮,为断点设置一个表达式。当这个表达式发生改变时,程序就被中断。底下设置包括“观察数组或者结构的元素个数”,似乎可以设置一个指针所指向的内存区的大小,但是我设置一个比较的值但是改动 
      范围之外的内存区似乎也导致断点起效。最后一个设置可以让程序先执行多少次然后才到达断点。
数据断点:数据断点只能在breakpoints对话框中设置。选择“data”页,就显示了设置数据断点的对话框。在编辑框中输入一个表达式,当这个 
      表达式的值发生变化时,数据断点就到达。一般情况下,这个表达式应该由运算符和全局变量构成,例如:在编辑框中输入 
      g_bflag这个全局变量的名字,那么当程序中有g_bflag= !g_bflag时,程序就将停在这个语句处。
消息断点:vc也支持对windows消息进行截获。他有两种方式进行截获:窗口消息处理函数和特定消息中断。在breakpoints对话框中选择messages页,就可以设置消息断点。如果在上面那个对话框中写入消息处理函数的名字,那么每次消息被这个函数处理,断点就到达(我觉得如果采用普通断点在这个函数中截获,效果应该一样)。如果在底下的下拉 
      列表框选择一个消息,则每次这种消息到达,程序就中断。
3 watch
      vc支持查看变量、表达式和内存的值。所有这些观察都必须是在断点中断的情况下进行。
      观看变量的值最简单,当断点到达时,把光标移动到这个变量上,停留一会就可以看到变量的值。
      vc提供一种被成为watch的机制来观看变量和表达式的值。在断点状态下,在变量上单击右键,选择quick watch, 
      就弹出一个对话框,显示这个变量的值。
      单击debug工具条上的watch按钮,就出现一个watch视图(watch1,watch2,watch3,watch4),在该视图中输入变量或者表达式,就可以观察 
      变量或者表达式的值。注意:这个表达式不能有副作用,例如++运算符绝对禁止用于这个表达式中,因为这个运算符将修改变量的值,导致 软件的逻辑被破坏。
4 memory
      由于指针指向的数组,watch只能显示第一个元素的值。为了显示数组的后续内容,或者要显示一片内存的内容,可以使用memory功能。在 
      debug工具条上点memory按钮,就弹出一个对话框,在其中输入地址,就可以显示该地址指向的内存的内容。
5 varibles
      debug工具条上的varibles按钮弹出一个框,显示所有当前执行上下文中可见的变量的值。特别是当前指令涉及的变量,以红色显示。
6 寄存器
      debug工具条上的reigsters按钮弹出一个框,显示当前的所有寄存器的值。
7 进程控制
      vc允许被中断的程序继续运行、单步运行和运行到指定光标处,分别对应快捷键f5、f10/f11和ctrl+f10。各个快捷键功能如下: 
      快捷键 说明 
      f5 继续运行 
      f10 单步,如果涉及到子函数,不进入子函数内部 
      f11 单步,如果涉及到子函数,进入子函数内部 
      ctrl+f10 运行到当前光标处。
8 call stack
      调用堆栈反映了当前断点处函数是被那些函数按照什么顺序调用的。单击debug工具条上的call stack就显示call 
      stack对话框。在callstack对话框中显示了一个调用系列,最上面的是当前函数,往下依次是调用函数的上级函数。单击这些函数名可以跳到对应的函数中去。
9 其他调试手段
      系统提供一系列特殊的函数或者宏来处理debug版本相关的信息,如下:
10 宏名/函数名 说明 
      trace 使用方法和printf完全一致,他在output框中输出调试信息 
      assert 它接收一个表达式,如果这个表达式为true,则无动作,否则中断当前程序执行。对于系统中出现这个宏 
      导致的中断,应该认为你的函数调用未能满足系统的调用此函数的前提条件。例如,对于一个还没有创建的窗口调用setwindowtext等。 
      verify 和assert功能类似,所不同的是,在release版本中,assert不计算输入的表达式的值,而verify计算表达式的值。
关注:
      一个好的程序员不应该把所有的判断交给编译器和调试器,应该在程序中自己加以程序保护和错误定位,具体措施包括:
对于所有有返回值的函数,都应该检查返回值,除非你确信这个函数调用绝对不会出错,或者不关心它是否出错。 
      一些函数返回错误,需要用其他函数获得错误的具体信息。例如accept返回invalid_socket表示accept失败,为了查明 
      具体的失败原因,应该立刻用wsagetlasterror获得错误码,并针对性的解决问题。 
      有些函数通过异常机制抛出错误,应该用try-catch语句来检查错误 
      程序员对于能处理的错误,应该自己在底层处理,对于不能处理的,应该报告给用户让他们决定怎么处理。如果程序出了异常, 
      却不对返回值和其他机制返回的错误信息进行判断,只能是加大了找错误的难度。 
      另外:vc中要编制程序不应该一开始就写cpp/h文件,而应该首先创建一个合适的工程。因为只有这样,vc才能选择合适的编译、连接 
      选项。对于加入到工程中的cpp文件,应该检查是否在第一行显式的包含stdafx.h头文件,这是microsoft visual 
      studio为了加快编译 速度而设置的预编译头文件。在这个#include 
      stdafx.h行前面的所有代码将被忽略,所以其他头文件应该在这一行后面被包含。
      对于.c文件,由于不能包含stdafx.h,因此可以通过project settings把它的预编译头设置为“不使用”,方法是: 
      弹出project settings对话框 
      选择c/c++ 
      category选择precompilation header 
      选择不使用预编译头。
      [url]http://www.yzcc.com/yzcc/vv/08475592434.html[/url]
      其他技巧:
      1.在调试状态下怎样查看错误消息(getlasterror())?
      通常可以用getlasterror()得到错误编号然后用formatmessage(...)得到错误描述。
      这里有一个更直接的办法:在watch窗口添加@err,hr
      2.怎样知道程序是否有内存泄漏(memory leak)?
      在vc开发环境下press 
      [f5],在调试状态下运行程序,测试有可能出现内存泄漏的操作,关闭程序,在output窗口查看运行信息.如果出现泄漏,在output中会有记录。当然,不能完全依靠这种方式来发现程序运行有内存泄漏。
      3.当某一变量满足某种条件时,停止在断点.
      如以下一程序片段:
      2 int ilocation;
      ...
      30 ilocation++
      ...
      要求: 在line30设有断点,并想在ilocation>100 
      本文来源:[url]http://blog.tianya.cn/blogger/post_show.asp?blogid=237133&postid=3587659[/url]
便于调试的代码风格:
不用全局变量
所有变量都要初始化,成员变量在构造函数中初始化
尽量使用const
详尽的注释
vc++编译选项:
总是使用/w4警告级别
在调试版本里总是使用/gz编译选项,用来发现在release版本中才有的错误
没有警告的编译:保证在编译后没有任何警告,但是在消除警告前要进行仔细检查
调试方法:
1、使用 assert(原则:尽量简单)
assert只在debug下生效,release下不会被编译。
例子:
char* strcpy(char* dest,char* source)
{
assert(source!=0);
assert(dest!=0);
char* returnstring = dest;
while((*dest++ = *source++)!= ‘/0’)
{
;
}
return returnstring;

2、防御性的编程
例子:
char* strcpy(char* dest,char* source)
{
if(source == 0)
{
assert(false);
reutrn 0;
}
if(dest == 0)
{
assert(false);
return 0;
}
char* returnstring = dest;
while((*dest++ = *source++)!= ‘/0’)
{
;
}
return returnstring;

3、使用trace
以下的例子只能在debug中显示,
例子:
a)、tracecstring cstest = “test”;
trace(“cstring is %s/n”,cstest);
b)、atltrace
c)、afxdump
ctime time = ctime::getcurrenttime();
#ifdef _debug
afxdump
#endif
4、用getlasterror来检测返回值,通过得到错误代码来分析错误原因
5、把错误信息记录到文件中
异常处理
程序设计时一定要考虑到异常如何处理,当错误发生后,不应简单的报告错误并退出程序,应当尽可能的想办法恢复到出错前的状态或者让程序从头开始运行,并且对于某些错误,应该能够容错,即允许错误的存在,但是程序还是能够正常完成任务。
调试技巧
1、vc++中f5进行调试运行
a)、在output debug窗口中可以看到用trace打印的信息
b)、 call stack窗口中能看到程序的调用堆栈
2、当debug版本运行时发生崩溃,选择retry进行调试,通过看call stack分析出错的位置及原因
3、使用映射文件调试
a)、创建映射文件:project settings中link项,选中generate mapfile,输出程序代码地址:/mapinfo: 
lines,得到引出序号:/mapinfo: exports。
b)、程序发布时,应该把所有模块的映射文件都存档。
c)、查看映射文件:见” 通过崩溃地址找出源代码的出错行”文件。
4、可以调试的release版本
project settings中c++项的debug info选择为program database,link项的debug中选择debug 
info和microsoft format。
5、查看api的错误码,在watch窗口输入@err可以查看或者@err,hr,其中”,hr”表示错误码的说明。
6、set next statement:该功能可以直接跳转到指定的代码行执行,一般用来测试异常处理的代码。
7、调试内存变量的变化:当内存发生变化时停下来。
常见错误
1、在函数返回的时候程序崩溃的原因
a)、写自动变量越界
b)、函数原型不匹配
2、mfc
a)、使用错误的函数原型处理用户定义消息
正确的函数原型为:
afx_msg lresult onmymessage(wparam wparam,lparam lparam);
3、谨慎使用terminatethread:使用terminatethread会造成资源泄漏,不到万不得已,不要使用。
4、使用_beginthreadex,不要使用create thread来常见线程。
windows 调试
1.windows跟踪语句:
(1)trace(_t(“warning (functionname):object %s not found./n”),objectname);
在输出的调试窗口会输出结果。跟踪信息输出到输出窗口output window中。[调试版本中使用]
(2)c++的c运行时刻库函数跟踪语句
    ansi c 运行时刻库函数没有跟踪语句,但是vc++的c运行时刻库函数有。可使用_rptn或_rptfn调试报告宏,但是你必须在程序中引用crtdbg.h,并利用c运行时刻函数库链接:
   _rpt0(reporttype,format);
   _rpt1(reporttype,format,arg1);
   _rpt2(reporttype,format,arg1,arg2);
   _rptf0(reporttype,format);
   _rptf1(reporttype,format,arg1);
   _rptf2(reporttype,format,arg1,arg2);
   例子:
          int a =1000,b=2000;
         int *p =&a;
         int *q = &b;
       _rptf2(_crt_warn,%x ,%x,p,q); //直接在outputwindow中输出
       _rptf2(_crt_error,%x ,%x,p,q);   //弹出error对话框
       _rptf2( _crt_assert,%x ,%x,p,q);   //弹出aeesrt对话框
reporttype:_crt_warn _crt_error _crt_assert
其中_crt_warn用于跟踪语句,_rptfn宏报告了源码文件名和调用这些宏的行号。[调试版本中使用]
可以使用_crtsetreportmode函数改变默认输出设置,(比如输出到调试器输出窗口,文件,消息框中),_crtsetreportfile可以指定将报告输出到哪个文件中。
(3)mfc中的跟踪语句
       区别:使用trace宏时,需要使用_t宏来格式化参数以正确解决unicode的校正,反之,在tracen类型的宏中,不必使用_t宏。
       trace(_t(ssss/n));
       trace2(%d r %d l/n,1,2);
(4)异常和返回值
c++程序中可以使用异常和返回值来返回状态信息。c语言返回一个函数的状态的最好方法就是它的返回值
try
{
//code may fail
}
catch
{
//handle the failure
}
只有在抛出异常的时候会有开销!catch块有一些开销,但是try块有很少的开销!只能在调试版中处理异常,并弹出messagebox,发布版不处理异常,为的就是优化。
     try
     {
       int *pint = 0;
       *pint =42;
     }
     catch(...)
     {
       messagebox(_t(exception was caught!),_t(exception test),mb_ok);   
     }
      (5)ansi c++ 运行时刻函数库跟踪
具体有:c语言的stderr和c++语言的clog流,在windows程序中没有任何效果!
(6)outputdebugstring (_t(“trace   debug info!/n”));[调试版本中使用]
       如果只想在调试版本中使用outputdebugstring,可以使用下面得宏来实现:
#ifdef   _debug
#define outputtracestring(text)   outputdebugstring(text)
#else
#define outputtracestring(text)   ((void) (0))
#endif
使用afxoutputdebugstring
afxoutputdebugstring宏使用和outputdebugstring一样的语法。
7.使用cobiect::dump
cobject类有一个转储(dump)虚拟函数,继承于它的所有子类函数都可以重载这个函数,输出它们的值。
例 1 -2:用下列语句输出cobject派生类pobject的值。afxdump是预定义的全局变量cdumpcontext,注意 cdumpcontext对最一般的内建数据类型及cobject的指针和引用支持插入操作符(
#if _debug
afxdump(pobiect);
pobject->dump(afxdump);
afxdump
#endif
例1-3:
afxdump
8.使用afxdump
afxdump是mfc中相当于cerr流的跟踪语句,所以你可以直接向它输出跟踪消息。
trace宏由afxdump实现,afxdump由afxoutputdebugstring实现。而afxoutputdebugstring在调试版中由_rpt0宏实现。可以使用下面的方法将afxdump重定向。
#ifdef _debug
cfile dumpfile; //必须为全局变量
     dumpfile.open(_t(dump.log),cfile::modewrite|cfile::modecreate);
     afxdump.m_pfile = &dumpfile;
#endif
9.使用afxdumpstack
可以使用afxdumpstack函数输出一个调用栈:
void afxapi afxdumpstack(dword dwtarget = afx_stack_dump_target_default);
参 数:dwtarget决定在调试和发布版本中输出到什么地方,可以输出到trace宏,outputdebugstring或到剪贴板。如果使用 afx_stack_dump_target_trace,含义是在调试版中输出到trace宏,而在发布版本中没有输出!如果你希望在发布版本中输出, 可使用afx_stack_dump_target_ods选项,而且必须在路径中有imagehlp.dll文件。在project& #61664;settingslinkcategorydebug both formats。 
10.atl跟踪语句 最基本的类型是atltrace函数:
inline void_cdecl atltrace(lpctstr format……);
atltrace (format……);
和mfc trace宏一样,它使用一个512字节固定大小的缓冲区,如果它的参数需要一个大于512字节的文本缓冲区,会导致一个出错的断言。实际上,它是使用api函数outputdebugstring实现的,因此它的输出不能改变到其他目标。
atl跟踪语句的另一个选择atltrace2函数:
inline void _cedecl atltrace2(dword category,uint level,lpctstr format,…);
atltrace(category,level,format);
该 函数增加了一个参数跟踪类别(category)(例如,atltracecom,atltracewindowing和 atltracecontrol)和一个参数严格级别。类别值是位掩码,atl自身使用介于0-2的级别值,0级指最严格的级别。 和atltrace函数类似,atltrace2函数只能用在调试版本中!
11.vc++消息pragma
pagama是一个编译时的跟踪语句,可用来警告在预处理过程中发现的潜在的编连(build)问题
12.处理长字符串:[例如处理sql语句]
(1)mfc下[只能调试版]
trace(longstring); //assert if _tcslen(longstring)>511,最大是512
#ifdef _debug
afxdump
#endif
(2)atl下[只能调试版]
atltrace(longstring); //assert if _tcslen(longstring)>511,最大是512
#ifdef _debug
outputdebugstring(longstring); //dosen’t assert for long strings 不需要判断
#endif
13.处理大量的跟踪输出。
如果跟踪消息数据产生的速度超过输出窗口处理的速度,那么消息会塞满缓冲区,数据会丢失。
简单方法:在输出大量数据的代码段,例如对象转储函数时候,调用 sleep api函数。例如:sleep(100).
 调试
1.当错误发生得时候,调用getlasterror()得到相应得错误码
错误码得位域有固定的格式,,在c:/program files/microsoft visual studio/vc98/include/winerror.h中有详细的说明:
//
//   values are 32 bit values layed out as follows:
//
//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
//   +---+-+-+-----------------------+-------------------------------+
//   |sev|c|r|     facility           |               code             |
//   +---+-+-+-----------------------+-------------------------------+
//
//       sev - is the severity code       安全代码
//
//           00 – success           0-安全   
//           01 – informational     1-信息
//           10 – warning         2-警告
//           11 – error             3-错误
//       c - is the customer code flag 
客户代码:0-microsoft定义的,1-客户定义的
//       r - is a reserved bit 保留位必须是0  
//       facility - is the facility code工具-microsoft 定义的
//       code - is the facility's status code 工具状态代码-microsoft或客户定义
   工具:更好的查看错误代码的方法,tools-》error lookup;在vc++调试器的watch窗口中输入@err监视getlasterror的返回数值,err是调试器用来显示最新错误码的一个虚拟寄 存器。还可以用 @err,hr将错误码转换为文本格式
技巧:在调试中,按f11键,alt+8显示反汇编窗口,在edit菜单中选择go to命令,在goto对话框的go to what中选择address选项,在enter address expression中输入导致崩溃的地址。
创 建映射文件的方法:projectsettingslinkgenerate mapfile.即可在工程的debug文件下看到。映射文件里面所有的公共符号都使用混合名字。可使用vc++的名字解析工具(undname)将混合 名字转换到原始名字。你可以在“开始””运行””cmd”输入
c:/documents and settings/zhangzhongping>cd c:/program files/microsoft visual studio/common/tools
输入:
c:/programfiles/microsoftvisualstudio/common/tools>undname ?randexception@@ygxhhhh@z
microsoft(r) windows nt(r) operating system
undname version 5.00.1768.1copyright (c) microsoft corp. 1981-1998
输出:
>> ?randexception@@ygxhhhh@z == randexception
当输入-f时,显示整个函数的原型!查看映射文件的时候,若出现重载函数,名字解析工具很有用!
输入:
c:/programfiles/microsoftvisualstudio/common/tools>undname-f ?randexception@@ygxhhhh@z
microsoft(r) windows nt(r) operating system
undname version 5.00.1768.1copyright (c) microsoft corp. 1981-1998
输出:
>> ?randexception@@ygxhhhh@z == void __stdcall randexception(int,int,int,int)
使用mfc和atl的def文件:
mfc的def文件在
c:/programfiles/microsoftvisual studio/vc98/mfc/src/intel目录下。
atl的def文件在
c:/program files/microsoft visual studio/vc98/atl/src目录下。
如 果用户运行自己的程序出现:the ordinal 6880 could not be located in the dynamic link library mfc42.dll信息。你可查看mfc42.def中对应的6880号函数:? screentoclient@cwnd@@qbexpautagrect@@@z @ 6880 noname.然后可以用名字解析工具解析混合名字如下:
输入:
c:/program files/microsoft visual studio/common/tools>undname -f ?screentoclient@cwnd@@qbexpautagrect@@@z @ 6880 noname
microsoft(r) windows nt(r) operating system
undname version 5.00.1768.1copyright (c) microsoft corp. 1981-1998
输出:
>> ?screentoclient@cwnd@@qbexpautagrect@@@z == public: void __thiscall cwnd::screentoclient(struct tagrect *)const
>> @ == @
>> 6880 == 6880
>> noname == noname
使用依赖关系浏览工具:
vc++依赖关系浏览工具(common/tools/depends.exe)
 内存泄漏的调试
在vc中我们使用_crtdumpmemoryleaks()来检测内存泄漏。
例子:
void ctracedlg::onbutton1() 
{
     int *pleak = new int; //故意造成内存泄漏
_crtsetdbgflag(_crtdbg_alloc_mem_df|_crtdbg_leak_check_df);
     //delete pleak;
     //pleak = null;
     _crtdumpmemoryleaks();//调用此函数在output window的debug窗口中显示内存泄漏的地址的数据。
}
debug窗口中显示:
detected memory leaks!
dumping objects ->
c:/programfiles/microsoftvisualstudio/myprojects/trace/tracedlg.cpp(181) : {89} normal block at 0x004213b0, 4 bytes long.
data: cd cd cd cd 
object dump complete.
注意:0xcd表示已经分配的数据
       0xdd表示已经释放的数据
       0xfd表示被保护的数据
断言
1.断言的特征:
(1)发现运行时刻错误(用户输入错误,资源分配错误,文件系统错误,硬件错误或其他类型错误)
(2)断言中的布尔表达式显示的是某个对象或者状态的有效性,而不是正确性
(3)断言在条件编译后只存在调试版本里面,特别是,断言只在_debug符号定义后,才能编译!
(4)断言不能包含程序代码,也不能有副作用,不能修改程序变量,也比能调用修改程序变量的函数
(5)断言只是给程序员提供有用信息的
2.断言的类型
(1)ansi c断言
void assert(expression)     包含在assert.h头文件中(最好不用assert)
原因:*当文件名太长的化,对话框显示的路径将会被截至掉!
*函数是由ansi ndebug函数驱动的,如果定义了ndebug后,断言就被取消!
如果要启用jit调试(just-in-time),在toolsoptionsdebug
中选择just-in-time debugging,默认也会勾选上ole rpc debugging
单击“重试(r)”就会显示出错误所在的标记行。
(2)c运行时刻函数库断言
_assert(boolean expression)   (crtdbg.h)[不用]
_asserte(boolean expression)   (crtdbg.h)[经常用这个]
_asserte宏更能给出更多简洁,有用的信息,显示了断言!
(3)mfc库中的断言
assert(boolean expression) assert宏和_assert宏显示的消息框相同。verify(boolean expression) verify 中的bool表达式在发布版本中被保留了下来。它简化了对返回值的判断!
cstring str;
verify(str.loadstring(ids_string));//不要用verify宏
assert_valid宏,被用来决定一个指向cobject派生类的对象的指针是否有效。assert(pobjectderivedfromcobject);主要是在使用cobject派生类对象之前调用,检查对象的有效性。
assert_kindof(classname,pobjectderivedfromcobject);
assert_pointer(pointer,pointertype);
assert_null_or_pointer(pointer,pointertype);
afxlsvalidaddress(const void*memoryaddress,uint memorybytes,bool iswriteable = true);
bool afxlsvalidstring (lpcstr string, int stringlength = -1);
(4)atl断言
如果你使用atl,crtdbg.h就包含在atlbase.h中。在任何atl代码中,atlassert才是你的选择,在atldef.h中你会发现atlassert是_assert的一个别名。
优点:在atl程序中使用atlassert可以让你使用自己的断言。
(5)考虑使用_asserte(false)来简化防御性的编程和断言的结合,要想得到描述性的断言消息,考虑使用_asserte(“problem description.”==0).
_asserte(this is the object requires the mm_text mapping mode == 0);
if (!expression)
{
 //handle error 
_assert(false); 
… 
}
if(failed(somefunction())) 
{
//handle error 
_assert(false) 
}
 (6)考虑使用_crtsetreportmode和_crtsetreportfile
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录