Debug和Release不一样

Debug 和 Release
并没有实质的限度,他们只是一组编译选项的集结,编译器只是依照约定的选项行动。 
   
相关经历: 转自http://dev.csdn.net/article/17/17068.shtm 

总结: 
Debug与Release分化的问题在刚开头编制代码时会平日爆发,99%是因为您的代码书写错误而导致的,所以不要动不动就说系统问题或编译器问题,
努力找找自己的由来才是素有。我过去就平常遭受那意况,经历过五次次的教训后自己就从头在意了,现在自我所写过的代码我早就好久没遭受那种题材了。上边是多少个幸免的地点,就算没有那种问题也应注意一下: 
1.
在意变量的开头化,越发是指针变量,数组变量的起始化(很大的情事下另作考虑了)。 

多年来写代码进度中,发现 Debug 下运行正常化,Release
下就会并发问题,让自己百思不得其解,而Release
下又不知道该怎么做进展调节,于是只可以使用printf格局逐步稳定到题目所在处,才意识原来是给定的一个数组未开始化,导致前面处理分外。网上查找了些资料,在那罗列汇总下,做为备忘~ 
一、Debug 和 Release 的区别 
        Debug
经常号称调试版本,它包涵调试音讯,并且不作任何优化,便于程序员调试程序。Release
称为公布版本,它往往是进展了各个优化,使得程序在代码大小和运作速度上都是最优的,以便用户很好地运用。 
     Debug 和 Release 的着实分化,在于一组编译选项。 
Debug 版本   
参数       含义   
/MDd /MLd 或 /MTd 使用 Debug runtime
library(调试版本的周转时刻函数库)   
/Od 关闭优化开关   
/D “_DEBUG” 相当于 #define
_DEBUG,打开编译调试代码开关(首要针对assert函数)   
/ZI   
创设 Edit and
continue(编辑继续)数据库,那样在调试进度中如果改动了源代码不需再度编译   
GZ 可以协助捕获内存错误  

  1. 变量。 
    世家都精通,debug跟release在开头化变量时所做的操作是不一致的,debug是将每个字节位都赋成0xcc(注1),而release的赋值近
    似于自由(我想是一贯从内存中分配的,没有先河化过)。那样就一览无遗了,即使您的次第中的某个变量没被开头化就被引用,就很有可能出现格外:用作控制变量将
    导致流程导向不均等;用作数组下标将会使程序崩溃;越发可能是导致其余变量的取缔确而滋生其余的错误。所以在宣称变量后当即对其初步化一个默认的值是最简单有效的主意,否则项目大了你找都没地点找。代码存在指鹿为马在debug方式下可能会忽略而不被察觉到,如debug格局下数组越界也基本上不会出错,在
    release中就爆出出来了,那一个找起来就比较难了:( 仍然友好多加留意吧 
    呵呵,就是我犯的问题~~ 
  2. 自定义音讯的音信参数。 
    MFC为大家提供了很好的音信机制,更有增无减了自定义信息,好处我就不用多说了。那也设有debug跟release的题目呢?答案是迟早的。在自定义消息的函数体申明时,时常会面到那般的写法:afx_msg LRESULT OnMessageOwn();
    Debug意况下一般不会有其他问题,而当您在Release下且三四线程或进程间选拔了新闻传递时就会促成无效句柄之类的失实。导致那么些颠倒是非间接原因是新闻体的参数没有增加,即应当写成:afx_msg LRESULT OnMessageOwn(WPARAM
    wparam, LPARAM lparam); (注2) 
  3. release方式下不失误,但debug格局下报错。 
    那种状态下基本上也是因为代码书写不正确引起的,查看MFC的源码,可以窥见好多ASSERT的说话(断言),那么些宏只是在debug方式下才使得,那么就
    清楚了,release版不报错是忽视了不当而不是没有错误,这恐怕存在很大的隐患,因为是Debug形式下,相比较便于调试,好好的反省自己的代码,再此
    就不多说了。 
  4. ASSERT, VERIFY, TRACE……….调试宏 
    那种景观很不难解释。举个例子:请在VC下输入ASSERT然后选中按F12跳到宏定义的地方,那里您就可以察觉Debug中ASSERT要履行
    AfxAssertFailedLine,而Release下的宏定义却为”#define ASSERT(f)
    ((void)0)”。所以注目的在于这一个调试宏的言语不要用程序相关变量如i++写操作的言辞。VERIFY是个不等,”#define
    VERIFY(f)
    ((void)(f))”,即执行,那里的功效就不多探索了,有趣味可自己探究:)。

[VC]DEBUG和RELEASE二〇〇七年0三月26日 周天 早晨 04:33    I.   
内存分配问题   
    
   1.    变量未开头化。下边的先后在debug中运行的很好。   
    
   thing    *    search(thing    *    something)   
   BOOL    found;   
   for(int    i    =    0;    i    <    whatever.GetSize();   
i++)   
   {   
   if(whatever[i]->field    ==    something->field)   
   {    /*    found    it    */   
   found    =    TRUE;   
   break;   
   }    /*    found    it    */   
   }   
   if(found)   
   return    whatever[i];   
   else   
   return    NULL;   
  
而在release中却相当,因为debug中会自动给变量初阶化found=FALSE,而在release版中则不会。所以尽可能的给变量、类或社团早先化。   
    
   2.    数据溢出的题材   
    
   如:char    buffer[10];   
   int    counter;   
    
   lstrcpy(buffer,    “abcdefghik”);   
    
  
在debug版中buffer的NULL覆盖了counter的上位,不过除非counter>16M,什么问题也未尝。不过在release版
中,counter可能被放在寄存器中,那样NULL就覆盖了buffer下边的长空,可能就是函数的回来地址,那将促成ACCESS   
ERROR。   
    
   3.    DEBUG版和RELEASE版的内存分配格局是分化的   
。如若你在DEBUG版中申请    ele    为   
6*sizeof(DWORD)=24bytes,实际上分配给您的是32bytes(debug版以32bytes为单位分配),   
而在release版,分配给您的就是24bytes(release版以8bytes为单位),所以在debug版中倘使你写ele[6],可能不会有何问题,而在release版中,就有ACCESS    VIOLATE。   
    
   II.    ASSERT和VERIFY   
    
   1.    ASSERT在Release版本中是不会被编译的。   
    
   ASSERT宏是这么定义的   
    
   #ifdef    _DEBUG   
   #define    ASSERT(x)    if(    (x)    ==    0)   
report_assert_failure()   
   #else   
   #define    ASSERT(x)   
   #endif   
  
实际上复杂一些,但无所谓。即使你在这一个语句中加了先后中务必要有些代码   
   比如   
    
   ASSERT(pNewObj    =    new    CMyClass);   
    
   pNewObj->MyFunction();   
    
   那种时候Release版本中的pNewObj不会分配到空间   
    
  
所以执行到下一个言辞的时候程序会报该程序执行了非法操作的荒唐。那时可以用VERIFY   
:   
    
   #ifdef    _DEBUG   
   #define    VERIFY(x)    if(    (x)    ==    0)   
report_assert_failure()   
   #else   
   #define    VERIFY(x)    (x)   
   #endif   
   那样的话,代码在release版中就足以实施了。   
    
   III.    参数问题:   
    
   自定义音讯的处理函数,必须定义如下:   
    
   afx_msg    LRESULT    OnMyMessage(WPARAM,    LPARAM);   
    
   重临值必须是HRESULT型,否则Debug会过,而Release出错   
    
   IV.    内存分配   
    
  
保险数据创设息争除的统一性:假设一个DLL提供一个可见创立数量的函数,那么那些DLL同时应当提供一个函数销毁那些多少。数据的创导和清除应该在同一个层次上。   
    
   V.    DLL的灾难   
    
   人们将差距版本DLL混合造成的差异性形象的名为   
“动态连接库的炼狱“(DLL    Hell)   
,甚至微软协调也如此说http://msdn.microsoft.com/library/techart/dlldanger1.htm)。   
    
   借使您的主次采用你自己的DLL时请留意:   
    
   1.   
不可以将debug和release版的DLL混合在一块儿使用。debug都是debug版,release版都是release版。   
    
  
解决办法是将debug和release的次序分别放在主程序的debug和release目录下   
    
    
   2.    千万不要认为静态连接库会解决问题,那只会使事态更不佳。   
    
   VI.    RELEASE板中的调试    :   
    
   1.    将ASSERT()    改为    VERIFY()    。找出概念在”#ifdef   
_DEBUG”中的代码,如果在RELEASE版本中要求这么些代码请将他们移到定义外。查找TRACE(…)中代码,因为那一个代码在RELEASE中
也不被编译。   
请认真检查那么些在RELEASE中须要的代码是不是并从未被便宜。   
    
   2.   
变量的初步化所带来的例外,在不相同的系统,或是在DEBUG/RELEASE版本间都设有这么的出入,所以请对变量举办初阶化。   
    
   3.   
是不是在编译时曾经有了警告?请将警告级别设置为3或4,然后保险在编译时从没警示出现.   
    
   VII.    将Project    Settings”    中    “C++/C    ”   
项目下优化增选改为Disbale(Debug)。编译器的优化可能引致众多奇怪的荒唐,请参http://www.pgh.net/~newcomer/debug_release.htm   
    
   1.    别的对RELEASE版本的软件也得以进行调试,请做如下改变:   
    
   在”Project    Settings”    中    “C++/C    ”    项目下设置   
“category”    为    “General”    并且将”Debug    Info”设置为   
“Program    Database”。   
    
   在”Link”项目下选中”Generate    Debug    Info”检查框。   
    
   “Rebuild    All”   
    
   如此做法会发出的一些范围:   
    
   不可以获取在MFC    DLL中的变量的值。   
    
   必须对该软件所拔取的拥有DLL工程都进展改动。   
    
   另:   
    
   MS    BUG:MS的一份技术文档中评释,在VC5中对此DLL的”马克斯(Max)imize   
Speed”优化增选并未被完全援救,因而那将会滋生内存错误并造成程序崩溃。   
    
   2.    http://www.sysinternals.com/
一个主次DebugView,用来捕捉OutputDebugString的输出,运行起来后(预计是自设为system   
debugger)就足以观望所有程序的OutputDebugString的输出。此后,你可以退出VC来运转你的顺序并见到调试音讯。   
    
   3.    有一个叫Gimpel   
Lint的静态代码检查工具,据说相比好用http://www.gimpel.com/   
可是要化$的。

VC下Debug和Release区别

  1. 自定义消息及其余表明的标准写法 
  2. 行使调试宏时使用后最好注释掉 
  3. 尽量选拔try – catch(…) 
  4. 尽心尽力利用模块,不但表达清楚而且有利于调试。 
    注1: 
    debug版开头化成0xcc是因为0xcc在x86下是一条int
    3单步中断指令,那样程序一旦跑飞了蒙受0xcc就会停下来,那和单片机编程时相似将没用的代码空间填入jmp
    0000语句是同样地转贴于:总计机二级考试_考试大【责编:drfcy 纠错】

   
Release 版本 参数含义   
/MD /ML 或 /MT 使用发表版本的运作时刻函数库   
/O1 或 /O2 优化开关,使程序最小或最快   
/D “NDEBUG” 关闭条件编译调试代码开关(即不编译assert函数)   
/GF 合仁同一视复的字符串,并将字符串常量放到只读内存,幸免被修改  

相关文章