Debug与Release版本的区别
- 格式:pdf
- 大小:311.13 KB
- 文档页数:22
Makefile条件编译debug版和release版⼀般,在开发测试阶段⽤debug版本,⽽上线发布⽤release版本。
使⽤Makefile定制编译不同版本,避免修改程序和Makefile⽂件,将会⼗分⽅便。
读了⼀些资料,找到⼀个解决⽅法,Makefile预定义宏与条件判断,结合make预定义变量,进⾏条件编译。
⽐如,有⼀个test.cpp,包含这段代码#ifdef debug//your code#endif你希望在debug版本要执⾏它,在release版本不执⾏。
我们可以写这样的⼀个Makefile:1 ver = debug23 ifeq ($(ver), debug)4 ALL: test_d5 CXXFLAGS = -c -g -Ddebug6else7 ALL: test_r8 CXXFLAGS = -c -O39 endif1011 test_d: test.do12 g++ -o $@ $^1314 test_r: test.ro15 g++ -o $@ $^1617 %.do: %.cpp18 g++ $(CXXFLAGS) $< -o $@1920 %.ro: %.cpp21 g++ $(CXXFLAGS) $< -o $@简单说⼀下,Makefile根据ver的不同定义了不同的编译选项CXXFLAGS与输出程序ALL,debug版本输出程序是test_d,release版本输出程序是test_rdebug版本编译选项是"-c -g -Ddebug",release版本编译选项是"-c -O3"debug版本object⽂件后缀是".do",release版本object⽂件后缀是".ro"debug版本编译选项使⽤"-D"定义宏debug,使得your code能够执⾏。
《深度探讨:C++ Release 和 Debug 编译的区别》在现今的软件开发行业中,C++ 语言作为一种经典而复杂的编程语言,一直以来都备受瞩目。
在 C++ 的编译过程中,Release 和 Debug 编译是两个极为重要的概念,它们对于软件的性能、稳定性和调试等方面都有着不可忽视的影响。
本文将从浅入深地探讨这两种编译方式的区别,以帮助读者更全面地理解 C++ 编译过程中的关键概念。
1. Release 和 Debug 编译概述让我们简要回顾一下 Release 和 Debug 编译的基本概念。
在 C++ 程序的编译过程中,Release 编译旨在生成优化后的可执行文件,以达到最佳性能和执行速度。
而 Debug 编译则注重在生成可执行文件的附带了调试信息,旨在为程序员提供更便捷、准确的调试功能。
2. Release 和 Debug 编译的差异接下来,我们来详细比较一下 Release 和 Debug 编译的主要差异。
在编译过程中,Release 编译会进行诸如函数内联、去除调试符号、优化代码等操作,以提高程序的执行效率和资源利用率。
而 Debug 编译则会保留调试信息、禁用优化等操作,以便于程序员在调试过程中准确地追踪变量、函数调用等信息。
3. Release 和 Debug 编译对程序性能的影响由于 Release 编译进行了大量的优化操作,因此生成的可执行文件往往具有更高的执行效率和更小的体积,适合部署到生产环境中。
而Debug 编译则由于保留了调试信息等,因此相对而言,生成的可执行文件会更大,执行效率较低,但却能够提供丰富的调试信息和功能。
4. 我对于 Release 和 Debug 编译的个人观点在我看来,Release 和 Debug 编译在实际开发中都具有其重要性。
Release 编译在保证程序性能的也能够节约资源,提高用户体验;而Debug 编译则在程序出现问题时,提供了必要的调试信息,有助于快速定位和修复 bug。
Debug与Release版本的区别本文主要包含如下内容:1. Debug 和 Release 编译方式的本质区别2. 哪些情况下 Release 版会出错3. 怎样“调试” Release 版的程序--------------------------------------关于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 并没有本质的界限,他们只是一组编译选项的集合,编译器只是按照预定的选项行动。
自己总是用VC平台来开发东西,但是有时候总是出这样那样的问题,在这里把Visual C++开发工具与调试技巧整理摘录如下,希望对大家有用,省去大家再去搜索的烦恼。
1.如何在Release状态下进行调试Project->Setting=>ProjectSetting对话框,选择Release状态。
C/C++标签中的Category选General,Optimizations选Disable(Debug),Debut info选Program Database。
在Link标签中选中Generate debug info复选框。
注:只是一个介乎Debug和Release的中间状态,所有的ASSERT、VERIFY都不起作用,函数调用方式已经是真正的调用,而不查表,但是这种状态下QuickWatch、调用队列跟踪功能仍然有效,和Debug版一样。
2. Release和Debug有什么不同Release版称为发行版,Debug版称为调试版。
Debug中可以单步执行、跟踪等功能,但生成的可执行文件比较大,代码运行速度较慢。
Release版运行速度较快,可执行文件较小,但在其编译条件下无法执行调试功能。
Release的exe文件链接的是标准的MFC DLL(Use MFC in a shared or static dll)。
这些DLL在安装Windows的时候,已经配置,所以这些程序能够在没有安装Visual C++ 6.0的机器上运行。
而Debug版本的exe链接了调试版本的MFC DLL文件,在没有安装Visual C++6.0的机器上不能运行,因为缺相应的DLL,除非选择use static dll when link。
3. ASSERT和VERIFY有什么区别ASSERT里面的内容在Release版本中不编译,VERIFY里面的内容仍然翻译,但不再判断真假。
所以后者更安全一点。
例如ASSERT(file.Open(strFileName))。
软件中Debug和Release到底有什么区别?有很多软件集成开发环境(IDE),比如VS(VC)、IAR等,在创建工程时都会自动生成有Debug 和 Release两个版本。
有些小伙伴比较纳闷,Debug 和 Release两个版本到底有什么区别?下面就来讲讲Debug 和 Release版本区别,及其相关的内容。
嵌入式专栏1关于Debug 和 Release版本Debug,顾名思义,就是调试版本;Release,即发布版本,或者说最终释放版本。
在一些项目中,会出现Debug 和 Release两个版本,比如:IAR EWARM:VS:一些初学者可能会问,他们二者到底什么差异?其实,Debug 和 Release两个版本其实主要就是工程配置不同。
我们这里拿IAR EWARM来说,主要是:Project -> Options 下面的配置选项不同:嵌入式专栏2Debug 和 Release差异Debug 和 Release两个版本,最根本的区别在于Debug版本多了一些与调试相关的配置内容。
1.生成调试信息Debug版本通常会生成调试信息,而Release通常没有这些信息。
比如IAR EWRAM:这里的“生成调试信息”其实包含了很多关于调试的信息,如果勾选会多出“.pbd”、 “.browse”、 “.linf”等与调试有关的信息。
补充①“.pbd”、 “.browse”为浏览信息的文件,“.linf”为链接配置相关的文件。
具体可以参看:IAR系列教程12_IAR文件类型描述。
补充②这个配置信息保存在“.ewp”(工程配置)文件下,包含了Debug 和 Release两个版本的配置信息:<configuration> <name>Debug</name> ...配置 </configuration><configuration> <name>Release</name> ...配置</configuration>你可以对比一下两个配置的差异,就知道二者的一些区别:补充③Keil MDK类似,也有类似的关于调试的配置:Projcet -> Options for Target:2.预处理Debug版本通常会有“DEBUG”相关的预处理(宏定义)不知道大家经常用类似下面的调试宏定义没有:#ifdef DEBUG //Debug调试版本相关的配置strongerHuang#else //Release发布版本相关的配置strongerHuang#endif比如最常见的就是printf(打印信息),会通过“DEBUG”调试信息打开/关闭打印输出信息。
Debug与Release版本的区别Debug 和Release 并没有本质的区别,他们只是VC预定义提供的两组编译选项的集合,编译器只是按照预定的选项行动。
如果我们愿意,我们完全可以把Debug和Release 的行为完全颠倒过来。
当然也可以提供其他的模式,例如自己定义一组编译选项,然后命名为MY_ABC等。
习惯上,我们仍然更愿意使用VC已经定义好的名称。
Debug版本包括调试信息,所以要比Release版本大很多(可能大数百K至数M)。
至于是否需要DLL支持,主要看你采用的编译选项。
如果是基于ATL的,则Debug和Release 版本对DLL的要求差不多。
如果采用的编译选项为使用MFC动态库,则需要MFC42D.DLL 等库支持,而Release版本需要MFC42.DLL支持。
Release不对源代码进行调试,不考虑MFC的诊断宏,使用的是MFC Release库,编译时对应用程序的速度进行优化,而Debug则正好相反,它允许对源代码进行调试,可以定义和使用MFC的诊断宏,采用MFC Debug库,对速度没有优化。
既然Debug和Release仅仅是编译选项的不同,那么为什么要区分Debug和Release 版本呢?Debug和Release,在我看来主要是针对其面向的目标不同的而进行区分的。
Debug通常称为调试版本,通过一系列编译选项的配合,编译的结果通常包含调试信息,而且不做任何优化,以为开发人员提供强大的应用程序调试能力。
而Release通常称为发布版本,是为用户使用的,一般客户不允许在发布版本上进行调试。
所以不保存调试信息,同时,它往往进行了各种优化,以期达到代码最小和速度最优。
为用户的使用提供便利。
下面仅就默认的Debug和Release版本的选项进行比较,详细的编译选项可以看MSDN 的说明。
我们将默认的Debug和Release的选项设置进行比较,过滤掉相同设置,主要的不同如下:编译选项:/Od /D "_DEBUG" /Gm /RTC1 /MDd /Fo"Debug““" /ZI链接选项:/OUT:"D:“MyProject“logging“Debug“OptionTest.dll" /INCREMENTAL Release设置:编译选项:/O2 /GL /D "NDEBUG" /FD /MD /Fo"Release““" /Zi链接选项:/OUT:"D:“MyProject“logging“Release“OptionTest.dll" /INCREMENTAL:NODebug 版本:/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 合并重复的字符串,并将字符串常量放到只读内存,防止被修改MDd与MD首先,Debug版本使用调试版本的运行时库(/MDd选项),Relase版本则使用的是发布版本的运行时库(vcrt.dll)。
Android签名详解(debug和release)1. 为什么要签名1) 发送者的⾝份认证由于开发商可能通过使⽤相同的Package Name来混淆替换已经安装的程序,以此保证签名不同的包不被替换2) 保证信息传输的完整性签名对于包中的每个⽂件进⾏处理,以此确保包中内容不被替换3) 防⽌交易中的抵赖发⽣,Market对软件的要求2. 签名的说明1) 所有的应⽤程序都必须有数字证书,Android系统不会安装⼀个没有数字证书的应⽤程序2) Android程序包使⽤的数字证书可以是⾃签名的,不需要⼀个权威的数字证书机构签名认证3) 如果要正式发布⼀个Android应⽤,必须使⽤⼀个合适的私钥⽣成的数字证书来给程序签名,⽽不能使⽤adt插件或者ant⼯具⽣成的调试证书来发布4) 数字证书都是有有效期的,Android只是在应⽤程序安装的时候才会检查证书的有效期。
如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能5) 签名后需使⽤zipalign优化程序6) Android将数字证书⽤来标识应⽤程序的作者和在应⽤程序之间建⽴信任关系,⽽不是⽤来决定最终⽤户可以安装哪些应⽤程序3. 签名的⽅法有三种打包⽅式:命令⾏⼿动打包、ant⾃动编译打包、eclipse+ADT编译打包,打包步骤如下:第⼀步⽣成R.java类⽂件:Eclipse中会⾃动⽣成R.java,ant和命令⾏使⽤android SDK提供的aapt.ext程序⽣成R.java。
第⼆步将.aidl⽂件⽣成.java类⽂件:Eclipse中⾃动⽣成,ant和命令⾏使⽤android SDK提供的aidl.exe⽣成.java⽂件。
第三步编译.java类⽂件⽣成class⽂件:Eclipse中⾃动⽣成,ant和命令⾏使⽤jdk的javac编译java类⽂件⽣成class⽂件。
第四步将class⽂件打包⽣成classes.dex⽂件:Eclipse中⾃动⽣成,ant和命令⾏使⽤android SDK提供的dx.bat命令⾏脚本⽣成classes.dex⽂件。
1.如何在Release状态下进行调试Project->Setting=>ProjectSetting对话框,选择Release状态。
C/C++标签中的Category 选General,Optimizations选Disable(Debug),Debut info选Program Database。
在Link 标签中选中Generate debug info复选框。
注:只是一个介乎Debug和Release的中间状态,所有的ASSERT、VERIFY都不起作用,函数调用方式已经是真正的调用,而不查表,但是这种状态下QuickWatch、调用队列跟踪功能仍然有效,和Debug版一样。
2. Release和Debug有什么不同Release版称为发行版,Debug版称为调试版。
Debug中可以单步执行、跟踪等功能,但生成的可执行文件比较大,代码运行速度较慢。
Release版运行速度较快,可执行文件较小,但在其编译条件下无法执行调试功能。
Release的exe文件链接的是标准的MFC DLL(Use MFC in a shared or static dll)。
这些DLL在安装Windows的时候,已经配置,所以这些程序能够在没有安装Visual C++ 6.0的机器上运行。
而Debug版本的exe链接了调试版本的MFC DLL文件,在没有安装Visual C++6.0的机器上不能运行,因为缺相应的DLL,除非选择use static dll when link。
3. ASSERT和VERIFY有什么区别ASSERT里面的内容在Release版本中不编译,VERIFY里面的内容仍然翻译,但不再判断真假。
所以后者更安全一点。
例如ASSERT(file.Open(strFileName))。
一旦到了Release版本中,这一行就忽略了,file根本就不Open()了,而且没有任何出错的信息。
深⼊了解Debug和Release的区别⼀:Bin ⽬录⽤来存放编译的结果,bin是⼆进制binrary的英⽂缩写,因为最初C编译的程序⽂件都是⼆进制⽂件,它有Debug和Release两个版本,分别对应的⽂件夹为bin/Debug和bin/Release,这个⽂件夹是默认的输出路径,我们可以通过:项⽬属性—>配置属性—>输出路径来修改。
obj是object的缩写,⽤于存放编译过程中⽣成的中间临时⽂件。
其中都有debug和release两个⼦⽬录,分别对应调试版本和发⾏版本,在.NET中,编译是分模块进⾏的,编译整个完成后会合并为⼀个.DLL或.EXE保存到bin⽬录下。
因为每次编译时默认都是采⽤增量编译,即只重新编译改变了的模块,obj保存每个模块的编译结果,⽤来加快编译速度。
是否采⽤增量编译,可以通过:项⽬属性—>配置属性—>⾼级—>增量编译来设置。
PRoperties⽂件夹定义你程序集的属性项⽬属性⽂件夹⼀般只有⼀个 AssemblyInfo.cs 类⽂件,⽤于保存程序集的信息,如名称,版本等,这些信息⼀般与项⽬属性⾯板中的数据对应,不需要⼿动编写。
.cs 类⽂件。
源代码都写在这⾥,主要就看这⾥的代码。
.resx 资源⽂件,⼀些资源存放在这⾥,⼀般不需要看。
.csproj C#项⽬⽂件,⽤VS打开这个⽂件就可以直接打开这个项⽬,⾃动⽣成,不需要看。
er 是⼀个配置⽂件,⾃动⽣成的,会记录项⽬⽣成路径、项⽬启动程序等信息。
也不需要看。
.Designer.cs 设计⽂件,⾃动⽣成,不需要看。
.aspx 是⽹页⽂件,HTML代码写在这⾥⾯。
sln:在开发环境中使⽤的解决⽅案⽂件。
它将⼀个或多个项⽬的所有元素组织到单个的解决⽅案中。
此⽂件存储在⽗项⽬⽬录中.解决⽅案⽂件,他是⼀个或多个.proj(项⽬)的集合 *.sln:(Visual Studio.Solution) 通过为环境提供对项⽬、项⽬项和解决⽅案项在磁盘上位置的引⽤,可将它们组织到解决⽅案中。
Debug与Release版本的区别Debug 和Release 并没有本质的区别,他们只是VC预定义提供的两组编译选项的集合,编译器只是按照预定的选项行动。
如果我们愿意,我们完全可以把Debug和Release的行为完全颠倒过来。
当然也可以提供其他的模式,例如自己定义一组编译选项,然后命名为MY_ABC等。
习惯上,我们仍然更愿意使用VC已经定义好的名称。
Debug版本包括调试信息,所以要比Release版本大很多(可能大数百K至数M)。
至于是否需要DLL支持,主要看你采用的编译选项。
如果是基于ATL的,则Debug和Release版本对DLL的要求差不多。
如果采用的编译选项为使用MFC动态库,则需要MFC42D.DLL等库支持,而Release版本需要MFC42.DLL支持。
Release不对源代码进行调试,不考虑MFC的诊断宏,使用的是MFC Release库,编译时对应用程序的速度进行优化,而Debug 则正好相反,它允许对源代码进行调试,可以定义和使用MFC的诊断宏,采用MFC Debug库,对速度没有优化。
既然Debug和Release仅仅是编译选项的不同,那么为什么要区分Debug和Release版本呢?Debug和Release,在我看来主要是针对其面向的目标不同的而进行区分的。
Debug通常称为调试版本,通过一系列编译选项的配合,编译的结果通常包含调试信息,而且不做任何优化,以为开发人员提供强大的应用程序调试能力。
而Release通常称为发布版本,是为用户使用的,一般客户不允许在发布版本上进行调试。
所以不保存调试信息,同时,它往往进行了各种优化,以期达到代码最小和速度最优。
为用户的使用提供便利。
下面仅就默认的Debug和Release版本的选项进行比较,详细的编译选项可以看MSDN的说明。
我们将默认的Debug和Release的选项设置进行比较,过滤掉相同设置,主要的不同如下:编译选项:/Od /D "_DEBUG" /Gm /RTC1 /MDd/Fo"Debug““" /ZI链接选项:/OUT:"D:“MyProject“logging“Debug“OptionTest.dll"/INCREMENTALRelease设置:编译选项:/O2 /GL /D "NDEBUG" /FD /MD /Fo"Release““" /Zi链接选项:/OUT:"D:“MyProject“logging“Release“OptionTest.dll"/INCREMENTAL:NODebug 版本:/MDd /MLd 或/MTd 使用Debug runtimelibrary(调试版本的运行时刻函数库)/Od 关闭优化开关/D "_DEBUG" 相当于#define _DEBUG,打开编译调试代码开关(主要针对assert函数)/ZI 创建Edit and continue数据库,在调试过程中如果修改了源代码不需重新编译/GZ 可以帮助捕获内存错误/Gm 打开最小化重链接开关,减少链接时间Release 版本:/MD /ML 或/MT 使用发布版本的运行时刻函数库/O1 或/O2 优化开关,使程序最小或最快/D "NDEBUG" 关闭条件编译调试代码开关(即不编译assert函数)/GF 合并重复的字符串,并将字符串常量放到只读内存,防止被修改MDd与MD首先,Debug版本使用调试版本的运行时库(/MDd选项),Relase版本则使用的是发布版本的运行时库(vcrt.dll)。
其区别主要在于运行时的性能影响。
调试版本的运行时库包含了调试信息,并采用了一些保护机制以帮助发现错误,也因此,其性能不如发布版本。
编译器提供的Runtime Library很稳定,不会造成Release版本错误,倒是由于Debug版本的Runtime Library加强了对错误的检测,如堆内存分配检查等,反而会报告错误,应当指出,如果Debug有错误,而Release版本正常,程序肯定是有Bug的,只是我们还没有发现。
ZI与Zi其次,/ZI选项与/Zi选项。
通过使用/ZI选项,可以在调试过程修改代码而不需要重新编译。
这是个调试的好帮手,可如果我们使用Release版本,这将变得不可行。
Od与O2/O2与/Od 选项:Od是关闭编译器优化,普遍用于Debug版本。
而O2选项是创建最快速代码,这当然是Release版本的不二选择。
RTCx选项/RTCx选项让编译器插入动态检测代码以帮助你检测程序中的错误。
比如,它会将局部变量初始化为非零值。
包括用0xCC初始化所有自动变量,0xCD初始化堆中分配的内存(即new的内存),使用0xDD填充被释放的内存(即delete的内存),0xFD初始化受保护的内存(debug版在动态分配内存的前后加入保护内存以防止越界访问)。
这样做的好处是这些值都很大,一般不可能作为指针,考试,大提示作为数值也很少用到,而且这些值很容易辩认,因此有利于在Debug版本中发现Release版才会遇到的错误。
另外,通过函数指针调用函数时,会通过检查栈指针验证函数调用的匹配性(防止原型不匹配)。
使用/RTCx选项会造成Debug版本出错,而Release版本正常的现象,因为Release版中未初始化的变量是随机的,很可能使指针指向了有效但是错误的地址,从而掩盖了错误。
这个编译选项只能在/Od选项下使用。
Gm,INCREMENTAL or NO编译选项中的Gm和链接选项中的INCREMENTAL都只为一个目的,加快编译速度。
我们经常遇上这样的问题,只修改了一个头文件,结果却造成所有动态库的重新编译。
而这两个选项就是为了解决这样的问题。
如果启用了/Gm开关,编译器在项目中的.idb文件中存储了源文件和类定义之间的依赖关系。
之后的编译过程中使用.idb 文件中的信息确定是否需要编译某个源文件,哪怕是此源文件已经包含了已修改的.h文件。
INCREMENTAL开关默认是开启的。
使用增量链接生成的可执行文件或者动态链接库会大于非增量链接的程序,因为有代码和数据的填充。
另外,增量链接的文件还包含跳转trunk以处理函数重定位到新地址。
MSDN 上明确指出:为确保最终发布版本不包含填充或者trunk,请非增量链接程序。
/GZ 选项:做以下这些事1.初始化内存和变量。
包括用0xCC 初始化所有自动变量,0xCD ( Cleared Data ) 初始化堆中分配的内存(即动态分配的内存,例如new ),0xDD ( Dead Data ) 填充已被释放的堆内存(例如delete ),0xFD( deFencde Data ) 初始化受保护的内存(debug 版在动态分配内存的前后加入保护内存以防止越界访问),其中括号中的词是微软建议的助记词。
这样做的好处是这些值都很大,作为指针是不可能的(而且32 位系统中指针很少是奇数值,在有些系统中奇数的指针会产生运行时错误),作为数值也很少遇到,而且这些值也很容易辨认,因此这很有利于在Debug 版中发现Release 版才会遇到的错误。
要特别注意的是,很多人认为编译器会用0 来初始化变量,这是错误的(而且这样很不利于查找错误)。
2. 通过函数指针调用函数时,会通过检查栈指针验证函数调用的匹配性。
(防止原形不匹配)3. 函数返回前检查栈指针,确认未被修改。
(防止越界访问和原形不匹配,与第二项合在一起可大致模拟帧指针省略FPO )通常/GZ 选项会造成Debug 版出错而Release 版正常的现象,因为Release 版中未初始化的变量是随机的,这有可能使指针指向一个有效地址而掩盖了非法访问。
_DEBUG与NDEBUG这是最重要的一个选项。
这两个是编译器的预处理器定义,默认情况下_DEBUG用于Debug版本,而NDEBUG用于Release版本。
它们可以说是重要的无以复加。
因为,assert系列的断言仅仅在_DEBUG下生效!下面是assert.h文件中摘出来的:C++代码1#ifdef NDEBUG2#define assert(_Expression) ((void)0)3#else /* NDEBUG */4#ifdef __cplusplus5extern "C" {6#endif /* __cplusplus */7_CRTIMP void __cdecl _wassert(__in_z const wchar_t *_Message, __in_z const wchar_t *_File, __in unsigned _Line);8#ifdef __cplusplus9}10#endif /* __cplusplus */11#define assert(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) )12#endif /* NDEBUG */可以看出在未定义_DEBUG时,assert变成一条空语句不被执行。
也就是说,我们现在所有发布的版本无法使用断言机制进行程序调试。
相关经验:1. 变量。
大家都知道,debug跟release在初始化变量时所做的操作是不同的,debug是将每个字节位都赋成0xcc,而release的赋值近似于随机。
如果你的程序中的某个变量没被初始化就被引用,就很有可能出现异常:用作控制变量将导致流程导向不一致;用作数组下标将会使程序崩溃;更加可能是造成其他变量的不准确而引起其他的错误。
所以在声明变量后马上对其初始化一个默认的值是最简单有效的办法,否则项目大了你找都没地方找。
代码存在错误在debug方式下可能会忽略而不被察觉到。
debug方式下数组越界也大多不会出错,在release中就暴露出来了,这个找起来就比较难了。
2. 自定义消息的消息参数。
MFC为我们提供了很好的消息机制,更增加了自定义消息,好处我就不用多说了。
这也存在debug跟release的问题吗?答案是肯定的。
在自定义消息的函数体声明时,时常会看到这样的写法:afx_msg LRESULT OnMessageOwn(); Debug 情况下一般不会有任何问题,而当你在Release下且多线程或进程间使用了消息传递时就会导致无效句柄之类的错误。
导致这个错误直接原因是消息体的参数没有添加,即应该写成:afx_msg LRESULT OnMessageOwn(WPARAM wparam, LPARAM lparam); 3. release模式下不出错,但debug模式下报错。