关于Debug和Release的区别

关于Debug和Release的区别之讨论本文主要包含如下内容:

1. Debug 和 Release 编译方式的本质区别
2. 哪些情况下 Release 版会出错
2. 怎样“调试” Release 版的程序


一、Debug 和 Release 编译方式的本质区别
Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程
序。Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度
上都是最优的,以便用户很好地使用。
Debug 和 Release 的真正秘密,在于一组编译选项。下面列出了分别针对二者的选项
(当然除此之外还有其他一些,如/Fd /Fo,但区别并不重要,通常他们也不会引起 Rele
ase 版错误,在此不讨论)
Debug 版本:
/MDd /MLd 或 /MTd 使用 Debug runtime library(调试版本的运行时刻函数库)
/Od 关闭优化开关
/D "_DEBUG" 相当于 #define _DEBUG,打开编译调试代码开关(主要针对
assert函数)
/ZI 创建 Edit and continue(编辑继续)数据库,这样在调试过
程中如果修改了源代码不需重新编译
/GZ 可以帮助捕获内存错误
/Gm 打开最小化重链接开关,减少链接时间

Release 版本:
/MD /ML 或 /MT 使用发布版本的运行时刻函数库
/O1 或 /O2 优化开关,使程序最小或最快
/D "NDEBUG" 关闭条件编译调试代码开关(即不编译assert函数)
/GF 合并重复的字符串,并将字符串常量放到只读内存,防止
被修改
实际上,Debug 和 Release 并没有本质的界限,他们只是一组编译选项的集合,编译
器只是按照预定的选项行动。事实上,我们甚至可以修改这些选项,从而得到优化过的调
试版本或是带跟踪语句的发布版本。

二、哪些情况下 Release 版会出错

有了上面的介绍,我们再来逐个对照这些选项看看 Release 版错误是怎样产生的

1. Runtime Library:

2. 优化:这类错误主要有以下几种:

(1) 帧指针(Frame Pointer)省略(简称 FPO ):在函数调用过程中,所有调用信息
(返回地址、参数)以及自动变量都是放在栈中的。若函数的声明与实现不同(参数、返
回值、调用方式),就会产生错误————但 Debug 方式下,栈的访问通过 EBP 寄存器
保存的地址实现,如果没有发生数组越界之类的错误(或是越界“不多”),函数通常能
正常执行;Release 方式下,优化会省略 EBP 栈基址指针,这样通过一个全局指针访问栈
就会造成返回地址错误是程序崩溃。C++ 的强类型特性能检查出大多数这样的错误,但如
果用了强制类型转换,就不行了。你可以在 Release 版本中强制加入 /Oy- 编译选项来关
掉帧指针省略,以确定是否此类错误。
(2) volatile 型变量:volatile 告诉编译器该变量可能被程序之外的未知方式修改
(如系统、其他进程和线程)。

(3) 变量优化:优化程序会根据变量的使用情况优化变量。例如,函数中有一个未被
使用的变量,在 Debug 版中它有可能掩盖一个数组越界,而在 Release 版中,这个变量
很可能被优化调,此时数组越界会破坏栈中有用的数据。当然,实际的情况会比这复杂得
多。与此有关的错误有:

3. _DEBUG 与 NDEBUG :当定义了 _DEBUG 时,assert() 函数会被编译,而 NDEBUG 时不
被编译。除此之外,VC++中还有一系列断言宏。这包括:

ANSI C 断言 void assert(int expression );
C Runtime Lib 断言 _ASSERT( booleanExpression );
_ASSERTE( booleanExpression );
MFC 断言 ASSERT( booleanExpression );
VERIFY( booleanExpression );
ASSERT_VALID( pObject );
ASSERT_KINDOF( classname, pobject );
ATL 断言 ATLASSERT( booleanExpression );
此外,TRACE() 宏的编译也受 _DEBUG 控制。

4. /GZ 选项:这个选项会做以下这些事

(1) 初始化内存和变量。
(2) 通过函数指针调用函数时,会通过检查栈指针验证函数调用的匹配性。(防止原
形不匹配)
(3) 函数返回前检查栈指针,确认未被修改.

三、怎样“调试” Release 版的程序

1. 前面已经提过,Debug 和 Release 只是一组编译选项的差别,实际上并没有什么
定义能区分二者。我们可以修改 Release 版的编译选项来缩小错误范围。如上所述,可以
把 Release 的选项逐个改为与之相对的 Debug 选项,如 /MD 改为 /MDd、/O1 改为 /Od
,或运行时间优化改为程序大小优化。注意,一次只改一个选项,看改哪个选项时错误消
失,再对应该选项相关的错误,针对性地查找。这些选项在 Project\Settings... 中都可
以直接通过列表选取,通常不要手动修改。由于以上的分析已相当全面,这个方法是最有
效的。
2.你也可以像 Debug 一样调试你的 Release 版,只要加入调试符号。在 Project/S
ettings... 中,选中 Settings for "Win32 Release",选中 C/C++ 标签,Category 选
General,Debug Info 选 Program Database。再在 Link 标签 Project options 最后
加上 "/OPT:REF" (引号不要输)。

 

相关经验: 转自http://dev.csdn.net/article/17/17068.shtm
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))",即执行,这里的作用就不多追究了,有兴趣可自己研究:)。总结:
Debug与Release不同的问题在刚开始编写代码时会经常发生,99%是因为你的代码书写错误而导致的,所以不要动不动就说系统问题或编译器问题, 努力找找自己的原因才是根本。我从前就常常遇到这情况,经历过一次次的教训后我就开始注意了,现在我所写过的代码我已经好久没遇到这种问题了。下面是几个 避免的方面,即使没有这种问题也应注意一下:
1. 注意变量的初始化,尤其是指针变量,数组变量的初始化(很大的情况下另作考虑了)。
2. 自定义消息及其他声明的标准写法
3. 使用调试宏时使用后最好注释掉
4. 尽量使用try - catch(...)
5. 尽量使用模块,不但表达清楚而且方便调试。
注1:
debug版初始化成0xcc是因为0xcc在x86下是一条int 3单步中断指令,这样程序如果跑飞了遇到0xcc就会停下来,这和单片机编程时一般将没用的代码空间填入jmp 0000语句是一样地转贴于:计算机二级考试_考试大【责编:drfcy 纠错】


[VC]DEBUG和RELEASE2007年08月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的"Maximize Speed"优化选项并未被完全支持,因此这将会引起内存错误并导致程序崩溃。

2. http://www.sysinternals.com/有 一个程序DebugView,用来捕捉OutputDebugString的输出,运行起来后(估计是自设为system debugger)就可以观看所有程序的OutputDebugString的输出。此后,你可以脱离VC来运行你的程序并观看调试信息。

3. 有一个叫Gimpel Lint的静态代码检查工具,据说比较好用http://www.gimpel.com/ 不过要化$的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在CCS(Code Composer Studio)中,DebugRelease是两种不同的编译方式,它们有以下几个区别。 首先,Debug版本和Release版本的生成方式不同。Debug版本在项目的Build Options中,通过设置Compiler -> Generate Debug选项来生成。而Release版本是指发布版本,它主要通过进行各种优化来确保程序在代码大小和运行速度上都是最优的。 其次,Debug版本和Release版本在编译选项上也有区别。它们分别有一组针对不同目的的选项。比如,Debug版本可能会开启一些额外的调试信息,以便在调试过程中能够更好地定位问题。而Release版本则会进行一些优化,例如删除不必要的调试信息、进行代码优化等,以提高程序的性能和效率。 最后,Debug版本和Release版本在使用上也存在一些差异。在调试过程中,Debug版本可以通过设置断点、单步执行等方式来逐行调试程序。而Release版本则不会包含这些调试信息,因此无法直接进行调试。但是,可以通过一些间接的方式来"调试" Release版本的程序,比如使用日志输出进行调试、使用追踪工具来分析程序的执行流程等。 总结起来,CCS中的DebugRelease区别主要在于生成方式、编译选项和调试能力上。Debug版本用于开发和调试阶段,可以提供更多的调试信息;而Release版本则是发布版本,通过各种优化来提高程序的性能和效率。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [关于DebugRelease之本质区别的讨论](https://blog.csdn.net/a675311/article/details/50562913)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [[转]CCS中DebugRelease的…](https://blog.csdn.net/pymqq/article/details/19977631)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值