0 VC++ 常见的内存异常值

* 0xcccccccc : Used by Microsoft's C++ Debugging runtime library to mark uninitialised stack memory

* 0xcdcdcdcd : Used by Microsoft's C++ Debugging runtime library to mark uninitialised heap memory

* 0xfeeefeee : Used by Microsoft's HeapFree() to mark freed heap memory

* 0xabababab : Used by Microsoft's HeapAlloc() to mark "no man's land" guard bytes after allocated heap memory

* 0xabadcafe : A startup to this value to initialize all free memory to catch errant pointers

* 0xbaadf00d : Used by Microsoft's LocalAlloc(LMEM_FIXED) to mark uninitialised allocated heap memory

* 0xbadcab1e : Error Code returned to the Microsoft eVC Debugger when connection is severed to the Debugger

* 0xbeefcace : Used by Microsoft .NET as a magic number in resource files

  以上异常值,比较常见的为前三种:

  对于0xcccccccc0xcdcdcdcd,在 Debug 模式下,VC 会把未初始化的栈内存上的指针全部填成 0xcccccccc ,当字符串看就是 “烫烫烫烫……”;会把未初始化的堆内存上的指针全部填成 0xcdcdcdcd,当字符串看就是 “屯屯屯屯……”。那么调试器为什么要这么做呢?VC的DEBUG版会把未初始化的指针自动初始化为0xcccccccc或0xcdcdcdcd,而不是就让取随机值,那是为了方便我们调试程序,如果野指针的初值不确定,那么每次调试同一个程序就可能出现不一样的结果,比如这次程序崩掉,下次却能正常运行,这样显然对我们解bug是非常不利的,所以自动初始化的目的是为了让我们一眼就能确定我们使用了未初始化的野指针了。

  对于0xfeeefeee,是用来标记堆上已经释放掉的内存。注意,如果指针指向的内存被释放了,变量本身的地址如未做改动,还是之前指向的内存的地址。如果该指针是一个类的指针,并且类中包含有指针变量,则内存被释放后(对于C++类,通常是执行delete操作),类中的指针变量就会被赋值为0xfeeefeee。如果早调试代码过程中,发现有值为0xfeeefeee的指针,就说明对应的内存被释放掉了,我们的代码已经出问题了。

  在此,就有一个关于VC DebugRelease模式下的变量初始化问题

  大家都知道,Debug跟Release在初始化变量时所做的操作是不同的,Debug是将每个字节位都赋成0xcc,而Release的赋值近似于随机(我想是直接从内存中分配的,没有初始化过)。这样就明确了,如果你的程序中的某个变量没被初始化就被引用,就很有可能出现异常:用作控制变量将导致流程导向不一致;用作数组下标将会使程序崩溃;更加可能是造成其他变量的不准确而引起其他的错误。所以,在声明变量后马上对其初始化一个默认的值是最简单有效的办法,否则项目大了你找都没地方找。代码存在错误在Debug方式下可能会忽略而不被察觉到,如Debug方式下数组越界也大多不会出错,在 Release中就暴露出来了,这个找起来就比较难了。

  

1 VC++ 之Debug运行正常,Release运行崩溃

  I、内存分配问题

  1.变量未初始化。

  在Debug中会自动给变量初始化,而在Release中则不会。所以:尽可能的给变量、类或结构初始化(很重要!)。

  2.数据溢出的问题

  如:

  char buffer[10];

  int counter;

  lstrcpy(buffer, "abcdefghik");

  如果您使用了strcpy(),lstrcpy() 等函数请注意检查。

  在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(pNewObj = new CMyClass);

  pNewObj->MyFunction();

  这种时候Release版本中的pNewObj不会分配到空间所以执行到下一个语句的时候程序会报该程序执行了非法操作的错误。这时可以用 VERIFY

  III.参数问题:

  自定义消息的处理函数,必须定义如下:

  afx_msg LRESULT OnMyMessage(WPARAM, LPARAM);

  返回值必须是HRESULT型,否则Debug会过,而Release出错

  IV.  内存分配

  保证数据创建和清除的统一性:如果一个DLL提供一个能够创建数据的函数,那么这个DLL同时应该提供一个函数销毁这些数据。数据的创建和清除应该在同一个层次上。

  V.DLL的灾难

  人们将不同版本DLL混合造成的不一致性形象的称为 “动态连接库的地狱“(DLL Hell)如果你的程序使用你自己的DLL时请注意:

  1.不能将Debug和Release版的DLL混合在一起使用。Debug都是Debug版,Release版都是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工程都进行改动

VC++ 之常见内存异常值的更多相关文章

  1. java常见内存溢出(OOM)

    jvm内存区域 程序计数器一块很小的内存空间,作用是当前线程所执行的字节码的行号指示器. java栈与程序计数器一样,java栈(虚拟机栈)也是线程私有的,其生命周期与线程相同.通常存放基本数据类型, ...

  2. iOS常见内存泄漏解决

    iOS常见内存泄漏解决     1 OC和CF转化出现的内存警告 CFStringRef cfString = CFURLCreateStringByAddingPercentEscapes(kCFA ...

  3. SQL SERVER 内存分配及常见内存问题(2)——DMV查询

    原文:SQL SERVER 内存分配及常见内存问题(2)--DMV查询 内存动态管理视图(DMV): 从sys.dm_os_memory_clerks开始. SELECT [type] , SUM(v ...

  4. SQL SERVER 内存分配及常见内存问题(1)——简介

    原文:SQL SERVER 内存分配及常见内存问题(1)--简介 一.问题: 1.SQL Server 所占用内存数量从启动以后就不断地增加: 首先,作为成熟的产品,内存溢出的机会微乎其微.对此要了解 ...

  5. JAVA JVM常见内存参数配置简析

    JVM常见内存参数配置简析   常见参数 -Xms .-Xmx.-XX:newSize.-XX:MaxnewSize.-Xmn(-XX:newSize.-XX:MaxnewSize) 简析 1.-Xm ...

  6. android 常见内存泄漏原因及解决办法

    android常见内存泄漏主要有以下几类: 一.Handler 引起的内存泄漏. 在Android开发中,我们经常会使用Handler来控制主线程UI程序的界面变化,使用非常简单方便,但是稍不注意,很 ...

  7. SQL SERVER 内存分配及常见内存问题 简介

    一.问题: 1.SQL Server 所占用内存数量从启动以后就不断地增加: 首先,作为成熟的产品,内存溢出的机会微乎其微.对此要了解SQL SERVER与windows是如何协调.共享内存.并且SQ ...

  8. Tomcat常见内存溢出的解决办法

    PermGen space错误解决方法 在看下文之前,首先要确认意见事情,就是你是如何启动tomcat的,我们在平时的开发环境当中,都是通过startup.bat方式启动tomcat的,那么你按照下面 ...

  9. [转]C++常见内存错误汇总

    在系统开发过程中出现的bug相对而言是比较好解决的,花费在这个上面的调试代价不是很大,但是在系统集成后的bug往往是难以定位的bug(最好方式是打桩,通过打桩可以初步锁定出错的位置,如:进入函数前打印 ...

随机推荐

  1. C#之LinQ数据库

    一:与LINQ有关的语言特性 1.隐式类型 (1)源起 在隐式类型出现之前, 我们在声明一个变量的时候, 总是要为一个变量指定他的类型 甚至在foreach一个集合的时候, 也要为遍历的集合的元素,指 ...

  2. js时间格式化(yy年MM月dd日 hh:mm)

    //时间格式化 Date.prototype.format = function (format) { var o = { "M+": this.getMonth() + 1, / ...

  3. 淘宝(阿里百川)手机客户端开发日记第十三篇 mysql的连接

    首先,我建立了一个包,里面存放了三个类文件,这三个文件是我从网络中找的,经过自己的整理.(我刚才查找想把这三个文件传上去,可能是自己对cnblogs的博客不太熟悉吧,没有找到,我只好粘贴代码了) 三个 ...

  4. Cocos2d-x 3.2 项目源代码从Mac打包到安卓教程【转自:http://www.2cto.com/kf/201410/342649.html】

    当我们用Xcode写好一个项目的源码之后,如何将它导入到安卓手机中呢?下面我来给大家一步一步讲解: 首先,我们打开终端,cd到Cocos2d-x 3.2文件夹中(注意不是你写的项目文件夹,而是官方项目 ...

  5. Android客户端的图形化拖放操作的设计实现

    为什么要拖放?拖放在某些UI交互中可以简化用户操作. 拖放的步骤包括哪些?“Drag and Drop”,拖放,顾名思义,总共就分三步:1, 开始拖起来:2, 正在拖:3, 放下,进行操作:在这三步里 ...

  6. mysql中like用法

    like 的通配符有两种 %(百分号):代表零个.一个或者多个字符. _(下划线):代表一个数字或者字符. 1. name以"李"开头 where name like '李%' 2 ...

  7. iOS 8 Auto Layout界面自动布局系列2-使用Xcode的Interface Builder添加布局约束

    http://blog.csdn.net/pucker/article/details/41843511 上一篇文章<iOS 8界面自动布局系列-1>简要介绍了iOS界面布局方式的前世今生 ...

  8. 写一个迷你版Smarty模板引擎,对认识模板引擎原理非常好(附代码)

    前些时间在看创智博客韩顺平的Smarty模板引擎教程,再结合自己跟李炎恢第二季开发中CMS系统写的tpl模板引擎.今天就写一个迷你版的Smarty引擎,虽然说我并没有深入分析过Smarty的源码,但是 ...

  9. espcms自定义表单邮件字段

    /include/inc_replace_mailtemplates.php中增加一行就可以了. 如:$replacemail['mailform'][] = array(name => '职位 ...

  10. Nunit-Writing Tests

    Nunit 测试可以被任意支持attributes的.net语言使用 Attributes被用于去标识测试类和测试方法,然后通过不同的方式修改他们的行为 Assertions针对一个或多个约束,测试一 ...