Debug和Release之本质区别
Debug 和 Release 编译方式的本质区别
Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。
Debug 和 Release 的真正秘密,在于一组编译选项。下面列出了分别针对二者的选项(当然除此之外还有其他一些,如/Fd /Fo,但区别并不重要,通常他们也不会引起 Release 版错误,在此不讨论)
| 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:链接哪种运行时刻函数库通常只对程序的性能产生影响。调试版本的 Runtime Library 包含了调试信息,并采用了一些保护机制以帮助发现错误,因此性能不如发布版本。编译器提供的 Runtime Library 通常很稳定,不会造成 Release 版错误;倒是由于 Debug 的 Runtime Library 加强了对错误的检测,如堆内存分配,有时会出现 Debug 有错但 Release 正常的现象。应当指出的是,如果 Debug 有错,即使 Release 正常,程序肯定是有 Bug 的,只不过可能是 Release 版的某次运行没有表现出来而已。 |
||||||||||
| 2. | 优化:这是造成错误的主要原因,因为关闭优化时源程序基本上是直接翻译的,而打开优化后编译器会作出一系列假设。这类错误主要有以下几种:
|
||||||||||
| 3. | _DEBUG 与 NDEBUG :当定义了 _DEBUG 时,assert() 函数会被编译,而 NDEBUG 时不被编译。除此之外,VC++中还有一系列断言宏。这包括:
此外,TRACE() 宏的编译也受 _DEBUG 控制。 |
||||||||||
| 4. | /GZ 选项:这个选项会做以下这些事:
通常 /GZ 选项会造成 Debug 版出错而 Release 版正常的现象,因为 Release 版中未初始化的变量是随机的,这有可能使指针指向一个有效地址而掩盖了非法访问。 |
怎样“调试” Release 版的程序
遇到 Debug 成功但 Release 失败,显然是一件很沮丧的事,而且往往无从下手。如果你看了以上的分析,结合错误的具体表现,很快找出了错误,固然很好。但如果一时找不出,以下给出了一些在这种情况下的策略。
| 1. | 前面已经提过,Debug 和 Release 只是一组编译选项的差别,实际上并没有什么定义能区分二者。我们可以修改 Release 版的编译选项来缩小错误范围。如上所述,可以把 Release 的选项逐个改为与之相对的 Debug 选项,如 /MD 改为 /MDd、/O1 改为 /Od,或运行时间优化改为程序大小优化。注意,一次只改一个选项,看改哪个选项时错误消失,再对应该选项相关的错误,针对性地查找。这些选项在 Project\Settings... 中都可以直接通过列表选取,通常不要手动修改。由于以上的分析已相当全面,这个方法是最有效的。 |
| 2. | 在编程过程中就要时常注意测试 Release 版本,以免最后代码太多,时间又很紧。 |
| 3. | 在 Debug 版中使用 /W4 警告级别,这样可以从编译器获得最大限度的错误信息,比如 if( i =0 )就会引起 /W4 警告。不要忽略这些警告,通常这是你程序中的 Bug 引起的。但有时 /W4 会带来很多冗余信息,如 未使用的函数参数 警告,而很多消息处理函数都会忽略某些参数。我们可以用:
#progma warning(disable: 4702) //禁止 来暂时改变警告级别,有时你可以只在认为可疑的那一部分代码使用 /W4。 |
| 4. | 你也可以像 Debug 一样调试你的 Release 版,只要加入调试符号。在 Project/Settings... 中,选中 Settings for "Win32 Release",选中 C/C++ 标签,Category 选 General,Debug Info 选 Program Database。再在 Link 标签 Project options 最后加上 "/OPT:REF" (引号不要输)。这样调试器就能使用 pdb 文件中的调试符号。但调试时你会发现断点很难设置,变量也很难找到——这些都被优化过了。不过令人庆幸的是,Call Stack 窗口仍然工作正常,即使帧指针被优化,栈信息(特别是返回地址)仍然能找到。这对定位错误很有帮助。 |
Debug和Release之本质区别的更多相关文章
- VS2008 Debug与Release的本质区别(转)
如何设置:工具栏“生成”→“配置管理器”→“活动解决方案配置” 对于VS2008的初次使用者来说,常会遇到的编译问题时,Debug版本运行正常,但在Release版本则不稳定或无法运行.以下是对Deb ...
- 关于Debug和Release之本质区别的讨论
一.Debug 和 Release 编译方式的本质区别 Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序.Release 称为发布版本,它往往是进行了各种优化 ...
- 探讨C++ 变量生命周期、栈分配方式、类内存布局、Debug和Release程序的区别
探讨C++ 变量生命周期.栈分配方式.类内存布局.Debug和Release程序的区别(一) 今天看博客园的文章,发现博问栏目中有一个网友的问题挺有趣的,就点进去看了下,标题是“C++生存期问题”,给 ...
- 项目发布Debug和Release版的区别
一.Debug和Release的区别 Debug:调试版本,包含调试信息,所以容量比Release大很多,并且不进行任何优化(优化会使调试复杂化,因为源代码和生成的指令间关系会更复杂),便于程序员调试 ...
- Debug与Release版本的区别详解
原文链接 Debug 和 Release 并没有本质的区别,他们只是VC预定义提供的两组编译选项的集合,编译器只是按照预定的选项行动.如果我们愿意,我们完全可以把Debug和Release的行为完全颠 ...
- Debug与Release版本的区别
Debug 和 Release 并没有本质的区别,他们只是VC预定义提供的两组编译选项的集合,编译器只是按照预定的选项行动.如果我们愿意,我们完全可以把Debug和Release的行为完全颠倒过来.当 ...
- vs中debug和release版本的区别(转)
vs中的程序有debug和release两个版本,Debug通常称为调试版本,通过一系列编译选项的配合,编译的结果通常包含调试信息,而且不做任何优化,以为开发 人员提供强大的应用程序调试能力.而Rel ...
- 在用VC编译下debug和release的什么区别
DEBUG和RELEASE 版本差异及调试相关问题:. 内存分配问题 1. 变量未初始化.下面的程序在debug中运行的很好. thing * search(thin ...
- 详解Qt,并举例说明动态编译(shared)和静态编译(static)以及debug and release 编译版本区别(可产生静态版的Debug版本,需要把-release 改为 –debug-and-release)
作为初入Qt学习的新人,花了整整一两天时间,对Qt编译版本等问题进行了一步步探索,首先感谢网站博客中文章,开始也不是很明白一些几个问题: 1.Qt版本问题 作为初学者,可能下载时这么多版本,如何选择呢 ...
随机推荐
- 启动hadoop,报错Error JAVA_HOME is not set and could not be found
报如错误:JAVA_HOME is not set and could not be found,可能是因为JAVA_HOME环境没配置正确,还有一种情况是即使各结点都正确地配置了JAVA_HOME, ...
- (转载)OSI七层参考模型和TCP/IP四层参考模型
Mallory 网络模型概念浅析 网络模型一般是指OSI七层参考模型和TCP/IP四层参考模型. #只是一种设计==模型# Open System Interconnect的缩写,意为开放式系统互 ...
- ubuntu中安装samba 分类: linux 学习笔记 ubuntu 2015-07-07 16:14 46人阅读 评论(0) 收藏
为了方便的和Windows之间进行交互,samba必不可少. 当然,他的安装使用也很简单: 安装: sudo apt-get install samba sudo apt-get install sm ...
- 【Android】Intent的使用-返回数据给上一个活动
第一个Activity A启动另外一个Activity B,B返回数据给A ============================================================= ...
- jQuery Validate 插件
>>>>>>>>>>>>>>>>>>>>>>>>> ...
- ReactiveCocoa 中signal(operation) then与doNext的区别
贴源码: doNext:实现的主要源代码 return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {return [ ...
- Base64的Java代码实现
欢迎拍砖~ 在数据二进制和byte互相转换的地方方法写得有点挫,不知道有没有更好的方法~ 顺便复习了java的一些基础东西,如位操作,原码反码补码 可以在这篇blog里学习到详细的知识点:http:/ ...
- 如何创建一个自己的【Composer/Packagist】包
首先让我们踏着欢快的脚步去Github创建一个新库,这里取名 composer-car,又欢快的将它克隆到本地: $ git clone git@github.com:victorruan/compo ...
- (转) Spring读书笔记-----部署我的第一个Spring项目
一.Spring介绍 Spring是一个轻量级的Java EE容器,它也是一种从实际需求出发,着眼于轻便,灵活,易于开发,易测试和易部署的轻量级开发框架.Spring它完成了大量开发中的通用步骤,留给 ...
- linq 中的分组查询
直接看代码: //一个字段分组 var data1 = from a in query group a by a.Name into b select new { Total = b.Sum(c=&g ...