当前位置: 首页 > 编程日记 > 正文

细说Debug和Release区别

VC下Debug和Release区别

最近写代码过程中,发现 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 可以帮助捕获内存错误

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

Debug 和 Release 并没有本质的界限,他们只是一组编译选项的集合,编译器只是按照预定的选项行动。
相关经验: 转自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/ 不过要化$的。

相关文章:

26期20180601目录管理

6月1日任务2.1/2.2 系统目录结构2.3 ls命令2.4 文件类型2.5 alias命令系统目录结构ls - list所有的用户在系统里都有自己的家目录&#xff0c;比如现在登陆的是root用户&#xff0c;登陆进去就是在root的家目录中&#xff0c;可以看到之前创建的公钥文件也是在这。但是如果是其…

thttpd安装与调试

http://www.acme.com/software/thttpd/ thttpd是一个非常小巧的轻量级web server&#xff0c;它非常非常简单&#xff0c;仅仅提供了HTTP/1.1和简单的CGI支持&#xff0c;在其官方网站上有一个与其他web server&#xff08;如Apache, Zeus等&#xff09;的对比图Benchmark&…

7 款可替代 top 命令的工具!(二)

作者 | JackTian来源 | 杰哥的IT之旅上一篇文章中给大家介绍了《11 款可替代 top 命令的工具&#xff01;》&#xff0c;今天我再来给大家推荐 7 款可替代 top 命令的工具&#xff0c;看完这两篇替代品的文章相信能让你对 Linux 操作系统下一个小小的命令大开眼界。一、atopato…

Error:Execution failed for task ':app:dexDebug'. com.android.ide.common.process.ProcessException

异常Log&#xff1a; Error:Execution failed for task ‘:app:dexDebug’. > com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process ‘command ‘/Library/……/java” finished with non-zero exit value 2 错误原因&am…

# 学号 2017-2018-20172309 《程序设计与数据结构》第十一周学习总结

---恢复内容开始--- 学号 2017-2018-20172309 《程序设计与数据结构》第十一周学习总结 教材学习内容总结 第23章 初识Android操作系统&#xff1a;一个多用户的Linux系统&#xff0c;一个运用程序运行时与其他的运用运行是独立的。发展&#xff1a;在Android4.4之前所有的应用…

php扩展xdebug基本使用

官网&#xff1a;http://www.xdebug.org/ 使用&#xff1a;http://www.xdebug.org/docs/安装 http://blog.csdn.net/21aspnet/article/details/7036087使用1.获取文件名&#xff0c;行号&#xff0c;函数名 xdebug_call_class() <?php function fix_string($a) { …

基于 Opencv 实现眼睛控制鼠标

作者 | 小白来源 | 小白学视觉如何用眼睛来控制鼠标&#xff1f;一种基于单一前向视角的机器学习眼睛姿态估计方法。在此项目中&#xff0c;每次单击鼠标时&#xff0c;我们都会编写代码来裁剪你们的眼睛图像。使用这些数据&#xff0c;我们可以反向训练模型&#xff0c;从你们…

linux 安装安装rz/sz 和 ssh

安装rz&#xff0c;sz yum install lrzsz; 安装ssh yum install openssh-server 查看已安装包 rpm -qa | grep ssh 更新yum源 1、备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2、下载新的CentOS-Base.repo 到/etc/yum.repos.d/ CentO…

css左固定右自适应常用方法

下面是几种方法的公用部分&#xff08;右自适应也是一样的&#xff0c;换一下方向&#xff09; html: <div class"demo"> <div class"sidebar">我是固定的</div> <div class"content">我是自适应的</div> </di…

nginx或httpd实现负载均衡tomcat(三)

接博客nginx或httpd实现反向代理tomcat并实现会话保持&#xff08;二&#xff09;实例四&#xff1a;使用httpd负载均衡后端tomcat服务第一步&#xff1a;准备两个tomcat服务器节172.16.240.203修改tomcat的server.xml配置文件&#xff0c;添加一个host。<Host name"to…

为 PHP 应用提速、提速、再提速

原文地址&#xff1a; http://www.ibm.com/developerworks/cn/opensource/os-php-fastapps1/ http://www.ibm.com/developerworks/cn/opensource/os-php-fastapps2/index.html为 PHP 应用提速、提速、再提速&#xff01;PHP 是一种脚本语言&#xff0c;常用于创建 Web 应用程序…

冬奥会夺金的背后杀手锏,竟是位 AI 虚拟教练

整理 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 近日&#xff0c;一则消息登上了热搜&#xff1a; 2月14日晚&#xff0c;在北京冬奥会自由式滑雪女子空中技巧决赛中&#xff0c;徐梦桃为中国代表团再添一金。她选择了难度系数4.293的动作&#xff0c…

Socket-实例

import socket,os,time server socket.socket() server.bind(("localhost",9999)) server.listen()while True:conn,addrserver.accept()print("new conn",addr)while True:print("等待新指令")data conn.recv(1024)if not data:print("客…

kcachegrind安装

http://kcachegrind.sourceforge.net/cgi-bin/show.cgi/KcacheGrindDownload http://hi.baidu.com/wangxinhui419/blog/item/4a7409c78c22b4c8d100608a.html http://wxiner.blog.sohu.com/156841393.html说明&#xff1a;linux下如果安装不上&#xff0c;直接下载windows版的吧…

Java【小考】

课上&#xff0c; 老师出了一个题: 考察&#xff1a;1、类的定义 2、类的属性 3、类的方法、重载、构造方法、代码块 题目是这样的&#xff1a; 设计 一个 类&#xff1a;Tree 要求&#xff1a; 1、包含main方法 2、属性&#xff1a;静态&#xff1a; String name ; double hei…

首个深度强化学习AI,能控制核聚变,成功登上《Nature》

编译 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 最近&#xff0c;DeepMind 开发出了世界上第一个深度强化学习 AI &#xff0c;可以在模拟环境和真正的核聚变装置中实现对等离子体的自主控制。 这项研究成果登上了《Nature》杂志。 托卡马克是一种用于…

windows下安装mysql8.0压缩版

下面总结下安装过程&#xff1a; 首先解压下载好的压缩版本。将解压后mysql的bin文件目录配置系统环境path变量中使用cmd打开命令窗口&#xff0c;输入mysqld --initialize命令初始化mysql的data数据目录&#xff0c;记住初始化完毕后&#xff0c;会在解压目录下生成一个data文…

Linux实时监控工具Nmon使用

官网&#xff1a;http://nmon.sourceforge.net/pmwiki.php?nMain.HomePage 下载&#xff1a;http://sourceforge.net/projects/nmon/files/nmon_linux_14g.tar.gz 解压&#xff1a; #chmod ux nmon_x86_64_sles11 #chmod 777 nmon_x86_64_sles11 版本不同&#xff0c;对应文件…

英特尔2022年投资者大会:公布技术路线图及重要节点

在英特尔2022年投资者大会上&#xff0c;英特尔CEO帕特基辛格和各业务部门负责人概述了公司发展战略及长期增长规划的主要内容。在半导体需求旺盛的时代&#xff0c;英特尔的多项长期规划将充分把握转型增长的机遇。在演讲中&#xff0c;英特尔公布了其主要业务部门的产品路线图…

20151102adonet2

实现增删改查 ExecuteNonQuery:执行增删改语句,返回值为该命令所影响的行数. ExecuteReader:执行查询,并返回 一个DataReader对象. ExecuteScalar:执行查询,返回查询数.(删除修改时判断记录是否存在) string strSql string.Format("select count(*) from RNews where New…

day07 -文件的基本操作

1、什么是文件&#xff1f; 文件是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位文件的操作核心就&#xff1a;读、写即我们只需要对于进行读写操作&#xff0c;就是对操作系统发起请求&#xff0c;然后由操作系统将用户或者应用程序对文件的读写操作转换成具体的硬盘…

淘宝Tengine服务器开源

http://tengine.taobao.org/index_cn.htmlTengine是由 淘宝核心系统部基于Nginx开发的Web服务器&#xff0c;它在 Nginx的基础上&#xff0c;针对大访问量网站的需求&#xff0c;添加了很多功能和特性。Tengine的性能和稳定性已经在大型的网站如 淘宝网&#xff0c; 淘宝商城等…

22个案例详解Pandas数据分析/预处理时的实用技巧,超简单

作者 | 俊欣来源 | 关于数据分析与可视化今天小编打算来讲一讲数据分析方面的内容&#xff0c;整理和总结一下Pandas在数据预处理和数据分析方面的硬核干货&#xff0c;我们大致会说Pandas计算交叉列表Pandas将字符串与数值转化成时间类型Pandas将字符串转化成数值类型Pandas当…

PL/SQL 中Returning Into的用法

ORACLE的DML语句中可以指定RETURNING INTO语句。RETURNING INTO语句的使用在很多情况下可以简化PL/SQL编程&#xff0c;少一次select into语句。DELETE操作&#xff1a;RETURNING返回的是DELETE之前的结果&#xff1b; INSERT操作&#xff1a;RETURNING返回的是INSERT之后的结果…

Java常用多线程辅助工具---countdownLatch

为什么80%的码农都做不了架构师&#xff1f;>>> 前言 上一篇博文说到semaphore&#xff0c;一个加强版的synchronized&#xff0c;该多线程辅助工具适用于控制对资源操作或者访问的场景。现在有一张场景是&#xff0c;需要等各个线程都都执行完了再进行下一步的操作…

听说,英特尔要对外开放 x86 授权?

整理 | 郑丽媛出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;同为主流芯片架构&#xff0c;相较于可申请授权的 ARM 和开源的 RISC-V&#xff0c;x86 一直以来都保持着“高高在上”的立场——唯有英特尔和 AMD 拥有 x86 授权。但目前看来&#xff0c;x86 的“高冷…

Linux下gedit显示行号

Gedit 编辑->视图

关于String数组的用法

android ContextWrapper.getResources(ContextWrapper.java:89) getResources()报错原因是在OnCreate方法外 无法完成Context的初始化 正确做法&#xff1a; String[] names;names new String[6];names[0] getResources().getString(R.string.a);names[1] getResources().g…

使用RabbitMQ做数据接收和处理时,自动关闭

场景&#xff1a;N个客户端向MQ里发送数据&#xff1b;服务器上有另一个控制台程序(假设叫ServerClient)来处理这里数据&#xff08;往数据库保存&#xff09;。方向为Client * n→MQSERVER→ServerClient 问题&#xff1a;ServerClient自动关闭&#xff0c;没有错误日志&#…

在 Python 中妙用短路机制

作者 | 费弗里来源 | Python大数据分析本期我们即将学习的是&#xff1a;Python中短路机制的妙用。不同于物理学中的「短路」&#xff08;Short circuit&#xff09;那般危险&#xff0c;Python中的短路机制非常有用&#xff0c;跟很多其他编程语言中的短路机制作用类似&#x…