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

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

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

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

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

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

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. MySQL 一些查询语句及技巧

    生成唯一随机数 # 非补0版本 SELECT FLOOR(100000 + RAND() * 899999) AS random_number FROM target_table WHERE &quo ...

  2. c++多态的实现

    在面试中常常会有面试官问道,c++的多态的实现机制.那么,多态到底该如何实现呢? 多态的简单介绍 一般来说,多态分为两种,静态多态和动态多态.静态多态也称编译时多态,主要包括模板和重载.而动态多态则是 ...

  3. composer install 卡壳

    曾经用npm依赖包的时候也遇到了相应的问题,总而言之在国内,各种依赖包就换成国内的镜像吧你懂得! linux 或 window 命令行输入 composer config -g repo.packag ...

  4. idea使用心得(2)-安装设置与创建web项目

    idea 是与eclipse齐名的IDE(集成开发工具),以智能闻名,不过对于熟悉eclipse的的用户来说,初次接触idea有些让人搞不清方向,下面介绍一下简单的使用 方式. 1.安装 官网下载ul ...

  5. 纯手写SpringMVC架构,用注解实现springmvc过程

    1.第一步,首先搭建如下架构,其中,annotation中放置自己编写的注解,主要包括service controller qualifier RequestMapping 第二步:完成对应的anno ...

  6. SpringBoot RESTful 应用中的异常处理小结

    转载:https://segmentfault.com/a/1190000006749441 @ControllerAdvice 和 @ExceptionHandler 的区别 ExceptionHa ...

  7. eclipse下的emacs风格快捷键

    Ieclipse emacs类快捷键 win + shift + b 切换设置断点 win + shift + f 格式化代码 win + shift + l 显示绑定的快捷键 win + shift ...

  8. 基于Redis的爬虫平台的实现

    一.需求: 1.数据抓取:目标数据的下载.解析.入库功能. 2.数据服务:黑名单.灰名单等查询服务. 3.平台监控:平台各个模块的数据实时监控. 二.WEB端效果展示: 三.架构设计 下载器.解析器. ...

  9. windows下mysqlbinlog二进制恢复

    Mysql数据恢复主要针对Windows游戏引擎服务器意外宕机,以及游戏出现重大BUG,导致需要回档. 注意:请在恢复数据库之前,备份目标数据库,切记! 一.Windows服务器意外DOWN机,数据库 ...

  10. Spring操作指南-AOP基本示例(基于注解)