写出本文仅仅是处于备忘的目的。

最近为现在做的软件添加了一个内存回收机制(以前处于某种内存只申请不释放,这并不等于内存泄露,因为我们知道这些内存块在内存中的位置)-- 在某一块内存不使用的时候将其释放掉,以防止内存缓慢增长。

由于以前没有释放内存,所以就不存在野指针的问题。于是乎肯定坑爹的事情就从内存释放开始了 。。。 /大哭

只从添加了内存释放机制之后软件就出现了各种崩溃 。。。

好了,闲话少说,直奔主题。

一个内存块很多地方引用,一旦一个地方释放内存,而且其他地方还在引用,那后果就 。。。

1.

当时我就想这个问题很简单啊,典型的野指针问题嘛 。。。

于是就给内存块的指针加了个引用计数(引用一次引用计数就加一次(原子操作)),释放内存块时并不是真的释放而是把引用计数减一(原子操作),当引用计数减到0时才会把内存给释放掉 。。。

说道这个各位看客一定以为这个问题就圆满解决了 。 其实  。。。 坑爹的事还没完 才 真正的刚刚开始 。。。 /大哭/大哭/大哭

加了引用计数之后,程序稳定比以前好多了,但是基本上每个1个小时就会崩溃一次 。。。

于是开始各种查找问题 。。。

后来发现问题还是出在资源释放的问题上,请看如下代码:

int Release()
{
InterlockedDecrement(&m_nRefCount); if (m_nRefCount <= 0)
{
        delete this;
}
     else{
       //do something
        ...
     }
return(m_nRefCount);
}

InterlockedDecrement的确是原子操作,但是后面的语句却不是,当多线程存在的时候可能 InterlockedDerement 会被执行两次 之后 第一个 的if 语句才会执行(如果想不明白就好好想,哈哈),这样的问题就是会导致 改内存块被释放两次 。。。

2.

吃一堑长一智 。。。 后来代码改成了这个样子

HRESULT Release()
{
int refCount = InterlockedDecrement(&m_nRefCount); if (refCount <= 0)
{
        delete this;
}
     else{
         //do something
         ...
     }
return(m_nRefCount);
}

这样调用InterlockedDerement之后得到的引用计数就不会受影响了 。。。 至少不会重复delete 自己吧 。。。

3.

这样修改之后软件的确更加稳定啦,运行5-6个小时没问题 。。。 但是 。。。 5-6个小时之后 ,软件依然崩溃,依然崩溃,依然崩溃 。。。

为什么呢?当时也是各种想不通 。。。 后来经过苦思冥想和各种极端调试手段终于发现了问题:

请看我增加引用的方法:

ULONG AddRef( void )
{
return InterlockedIncrement(&m_nRefCount) ;
}

原来我对内存的引用并不是先引用而后释放,而是 引用和释放穿插使用的,由于是多线程,同时增加引用和资源释放并不是互斥执行的,有可能会同时执行,同时执行,同时执行 。。。

当同时执行的时候就会有极小的概率导致引用计数减为0,到delete语句被执行的间隙,存在一次引用计数加一的动作 ,这样内存块看似没有被释放(引用计数为1)其实已经释放了,这样就产生了野指针,产生了野指针,产生了野指针!!!

找到了问题,却不好解决 。。。 因为不能再release和addref里面添加锁,因为使用它的地方太多了,影响效率不说 还可能会导致死锁。

后来只能在可能会出现这种状况的地方添加锁,还好能够产生这种状况的地方不多。

后来问题圆满解决 。。。

C++内存泄露之野指针的更多相关文章

  1. C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针

    C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针 (1)开辟的内存没有释放,造成内存泄露 (2)野指针被使用或释放 (3)非法释放指针 (1)开辟的内存没有释放.造成内存泄露,以下的样 ...

  2. c/c++:内存泄露和野指针的概念

    内存泄漏 用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元.直到程序结束.即所谓内存泄漏.    注意:内存泄漏是指堆内存的泄漏. 简单的说就是申请了一块内存空间,使用 ...

  3. C/C++中内存泄漏、内存溢出与野指针的解释与说明

    1.内存泄漏 内存泄漏是指我们在堆中申请(new/malloc)了一块内存,但是没有去手动的释放(delete/free)内存,导致指针已经消失,而指针指向的东西还在,已经不能控制这块内存, 所以就是 ...

  4. iOS开发_内存泄漏、内存溢出和野指针之间的区别

    今天,在工作群中,被问到了内存泄漏和野指针指向的区别,自己答的不是很好,特意回来查了资料,在博文中总结一下经验,欢迎指正. 内存泄漏:是指在堆区,alloc 或new 创建了一个对象,但是并没有放到自 ...

  5. Objective-C 【多个对象内存管理(野指针&内存泄漏)】

    ------------------------------------------- 多个对象内存管理(野指针&内存泄漏) (注:这一部分知识请结合"单个对象内存管理"去 ...

  6. 七.OC基础加强--1.内存管理 2.野指针,内存泄露 3.set方法的内存管理 4.@property参数 5.@class和循环retain的使用 6.NSString的内存管理

    1,内存管理简单介绍 1,为什么要有内存管理? malloc selloc dealloc```需要回头复习 一般的内存 4s 是512m内存:6 是1024m内存: 当内存过大时,会耗尽内存.出现程 ...

  7. Objective-C 【单个对象内存管理(野指针&内存泄露)】

    ------------------------------------------- 单个对象内存管理 (1)野指针 ①定义了一个指针变量,但是并没有赋初值,它随机指向一个东西 ②某指针变量指向的内 ...

  8. 从默认析构函数学习c++,new,delete,内存泄漏,野指针

    默认析构函数:当系统没有显式定义析构函数,编译器同样会为对象定义一个默认析构函数,默认的析构函数只能释放普通数据成员所占用的空间,无法通过释放通过new和malloc进行申请的空间,因此避免内存泄漏, ...

  9. OC-引用计数器,内存管理,野指针

    总结 全局断点 →-->+-->Add Exception Breakpoint 开启僵尸监听 打开Edit scheme -->Diagnostics-->Enable Zo ...

随机推荐

  1. Objective的字符串拼接 似乎没有Swift方便,但也可以制做一些较为方便的写法

    NSString *str1 = @"字符串1"; NSString *str2 = @"字符串2"; //在同样条件下,Objective的字符串拼接 往往只 ...

  2. [转]你不需要jQuery

    完全没有否定jQuery的意思,jQuery是一个神奇的.非常有用的工具,可以节省我们大量的时间. 但是,有些时候,我们只需要jQuery的一个小功能,来完成一个小任务,完全没有必要加载整个jQuer ...

  3. visual stdio 2015安装配置及原理

    安装与配置: 1.先配置好IIS,再安装visual stdio,主要原因系统会自注册.net Framework,若顺序不正确,则需手动注册,步骤: a. IIS可承载的Web核心 b. IIS6 ...

  4. Python 中的urlencode和urldecode

    python中的urlencode与urldecode 发表于2013/11/13 16:04:09  79983人阅读 分类: python 当url地址含有中文,或者参数有中文的时候,这个算是很正 ...

  5. 我喜欢ASP.NET的MVC因为它牛逼的9大理由(转载)

    我很早就关注ASP.NET的mvc的,因为最开始是学了Java的MVC,由于工作的原因一直在做.Net开发,最近的几个新项目我采用了MVC做了,我个一直都非常喜欢.Net的MVC.我们为什么使用MVC ...

  6. Hive&Hbase

    1. 两者分别是什么? Apache Hive是一个构建在Hadoop基础设施之上的数据仓库.通过Hive可以使用HQL语言查询存放在HDFS上的数据.HQL是一种类SQL语言,这种语言最终被转化为M ...

  7. exit和return的区别

     主要有几下几个不同点:     1. return返回函数值,是关键字:exit是一个函数.     2. return是语言级别的,它表示了调用堆栈的返回:而exit是系统调用级别的,它表示了一个 ...

  8. linq实现数组转符号分割的字符串(备忘)

    fitemidstr = string.Join(",", detailpre1.Select(i => i.Key.ToString()).ToArray());

  9. sql服务器启动不了问题

    问题:the the service mysql56 failed the most recent status change request with the messagethe service  ...

  10. HTML之Hello World

    之前学过一段时间的HTML相关知识,但是已经有将近一年多时间没有用过了,曾经学过的知识基本都忘记了,所以要从头开始学习. 例子:Hello World <!DOCTYPE html> &l ...