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版本问题 作为初学者,可能下载时这么多版本,如何选择呢 ...
随机推荐
- 从零開始开发Android版2048 (一)初始化界面
自学Android一个月多了,一直在工作之余零零散散地看一些东西.感觉经常使用的东西都有些了解了,可是一開始写代码总会出各种奇葩的问题.感觉还是代码写得太少.这样继续杂乱地学习下去进度也太慢了,并且学 ...
- oracle2
为什么选择oracle--性能优越 概述:目前主流数据库包括 微软: sql server和access 瑞典MySql: AB公司mysql ibm公司: db2(处理海量) 美国Sybase公司: ...
- Windows下Memcached在.Net程序中的实际运用(从Memcached客户端Enyim的库的编译到实际项目运用)
1.一点基础概念 2.获取EnyimMemcached客户端的源代码并编译出动态库 3.Memcached的服务器安装(windows server) 4.在web项目中实战 一.基础概念 memca ...
- MySQL查询
DQL 操作 DQL 数据查询语言(重要) 数据库执行DQL语句不会对数据做出任何改变,而是让数据库发送结果集给客户端. 查询返回的结果是一张虚拟表. 查询关键字:SELECT ...
- 禁止输出重定向(>)覆盖已存在文件(防止误操作)
在输出重定向中,>表示重定向并覆盖已有文件内容,为了防止误操作,覆盖重要的内容,可以使用如下命令: set -C 这样输出重定向到一个已有文件就会提示: cannot overwrite exi ...
- springmvc使用aop心得
第一步:创建aop拦截类: @Component @Aspect public class ControllerSelectorInterceptor { @Before("executio ...
- a标签的简单用法
1.href="#"的作用:页面中有滚动,可以直接回到顶部. <a href="#">回到最顶端</a> 2.href="ur ...
- c#中string.trimstart() 和string.trimend() 的用法
trim(),trimstart(),trimend()这样写是去掉空格,trimstart(a)是去掉字符串开始包含char[] a的字符,trimend同trimstart. 例:char[] a ...
- CodeSmith中SchemaExplorer属性的介绍
CodeSmith与数据库的联系,在CodeSmith中自带一个程序集SchemaExplorer.dll,这个程序集中的类主要用于获取数据库中各种对象的结构. <%@ Property Nam ...
- ios专题 - 安全
iOS通过以下几种机制来保全整个系统的安全性: 一:系统结构 所有iOS设备中,系统与硬件都高度集成,从系统启动.系统更新.应用的安装.应用的运行时等多个方面来保全系统的安全,具体包括: 1:所有iO ...