Cocos2d-x内存管理

Cocos2d-x内存管理浅解

1、首先我们知道内存管理分为c++自身管理机制以及Cocos2d-x内存管理机制。在c++中,内存分为堆区、栈区、静态存储区(全局存储区)、常量存储区、自由存储区。

主要先说一下堆区和栈区。堆区主要由new和malloc分配,new与delete,malloc与free成对出现,保证内存的分配与回收。堆内存分配地址是逐渐增大的,这一点与栈区相反,我们都知道栈是先进后出,所以栈的存储方向是内存地址逐渐减小的。栈中的内存也是系统自动回收的,这个我们不需要考虑自己管理内存泄露的问题,而堆区的释放一定要注意使用完后手动释放,不然就会出现内存泄露的问题。在小的程序中我们可能感受不到这个问题的严重性,在成品软件中我们必须要严防这个问题,很多时候在PC端开发的时候没有感觉到任何问题,但是版本发布后就会发现出现很多Crash,这个其中很重要的原因就是因为内存泄露。我们经常说手机内存的大小,当手机装了一大堆软件之后就会变得非常卡,就是这个原因,内存泄露之后正在运行的程序越来越感觉内存不够用,严重的就是不断卡顿然后Crash。所以要养成习惯,注意内存使用与回收的问题。

另外关于静态存储区的问题,我们需要注意几点,静态函数与静态成员变量是类所拥有的不是某个对象所独有的,静态成员可以由类名调用,统一赋值或改变,这是静态成员的优点同样也是缺点,当我们需要一个全局变量时我们一般会使用静态变量,使用十分方便但是当不同的对象需要对其改变而其他对象不需要时则会发生数据不稳定的情况,这是我们不愿意看到的。对于其优点我们一般在需要全局出现的地方使用,例如单例模式中,我们需要一个单例类,单例类对象的初始化函数就是静态成员,表明全局性,而我们知道静态函数只能操作静态数据,所以我们的成员指针也必须是静态的。这样我们就实现了对象的唯一性。

2、cocos2d-x内存管理机制

cocos2d-x内存管理总的原则是谁拥有 , 谁管理 , 谁释放。

cocos2d-x使用引用计数对内存进行管理。当我们在堆上分配一块内存空间的时候,这个对象的引用计数就是1,当有对象要引用这块内存空间的时候,这个引用计数就增加1,当有对象不再引用这块内存的时候引用计数就减1,当这个引用计数减为0的时候就使用delete删除掉这块内存,这样就做到了当有对象引用的时候会正常的访问这块内存,引用完毕也可以正常的回收。但是如果每一个对象全部是手动retain和release,那么我们的代码里就会到处都是retain、release,既不美观方便也容易出错,于是我们引入了自动内存管理池对对象进行管理。看如下代码,引用计数问题就会比较清楚了。

//对象创建的时候引用计数被设置为1,这个是在它的构造函数中完成的,它会先调用父类CCOjbect的构造函数

//CCObject的构造函数如下所示

//CCObject::CCObject(void)

//, m_uReference(1) {}// when the object is created, the reference count of it is 1

CCSprite * sprite = new CCSprite();

CCLOG("retain count:%d",sprite->retainCount()); //值为1

//调用retain方法的时候引用计数增加1

sprite->retain();

CCLog("retain count:%d",sprite->retainCount());

//调用release方法的时候引用计数减一,当这个引用计数减为0的时候,在release方法中会delete掉这个对象

sprite->release();

CCLog("retain count:%d",sprite->retainCount());

//当我们调用autorelease方法的时候会调用这段代码

//CCPoolManager::sharedPoolManager()->addObject(this);

//调用autorelease方法的时候对象会被放到自动回收池中,这个自动回收池在每帧结束的时候会调用一次对象的release方法

sprite->autorelease();

CCLog("retain count:%d",sprite->retainCount());//记住 autoRelease并不会增加引用计数

上面代码有一处不太好理解就是经常说的自动回收机制,也就是autorelease方法,这个方法到底做了什么,有什么作用,我们需要好好的搞清楚!首先需要澄清的一个概念就是帧,在Cocos2d-x中我们经常说每秒多少多少帧,其实这个帧需要多少时间不是固定的,这个需要看每帧我们需要做多少事情,如果每一帧我们需要渲染很多的东西,那这一帧执行的时间当然就会很长的,游戏显得就会很卡,这个时候每秒的帧率就会下降的,所以不是时间决定的帧率,而是帧影响的时间!这个自动回收池就是在每帧结束的时候起作用的,在游戏的每一帧都会有一个大的循环,在一帧开始之前,系统建立了一个内存回收池,在这一帧的过程中,当我们调用了autorelease方法以后,我们的对象就会放到这个内存回收池中,当一帧结束的时候这个内存回收池就会释放掉,这个时候在内存回收池中的对象就会被release一下,也就是说引用计数就会减一,如果这个时候引用计数为0,就会删除对象了。如果引用计数不为0的话对象是不会被删除的,这时改由对象的持有者管理其生存周期了,下一帧开始的时候系统又会创建一个内存回收池,这个时候在上一次添加的对象这个时候是不会重新添加到这个内存回收池中的,在这个内存回收池中的对象是你在这一帧中调用了autorelease函数的对象。好了下面我们来看一个例子来了解下这个自动回收机制怎么就做到自动回收的。

<code cpp>

//在create的时候调用了sprite的autorelease方法

CCSprite * sprite = CCSprite::create("HelloWorld.png");

CCLog("retain count:%d",sprite->retainCount());         //retain 1

this->addChild(sprite);

CCLog("retain count:%d",sprite->retainCount());         //retain 2

分析一下上边的代码,调用了create工厂方法以后,内部的实现是先new一个CCSprite的对象,这个时候引用计数加1,然后调用autorelease方法,将这个对象放到了自动回收池中,因为这一帧还没有结束,当然引用计数就还是1,所以打印的结果就是1,当我们调用addChild的时候,传入这个CCSprite对象,这个时候在当前层接受了这个对象以后会把它的引用计数加一,表明当前层正在使用这块内存空间,所以现在的retain就是2了。当这一帧结束的时候自动回收池会将对象的引用计数-1,所以现在就只有CCLayer在引用这个对象了,当CCLayer析构的时候,它会调用这个对象的release方法,这个时候当然就会删除了这个CCSprite对象了。所以自动回收机制的自动就是在这一帧结束的时候将对象开始new的时候加的那个引用计数减掉,而让引擎中持有对象引用的其他对象去管理这个对象,当持有者removeChild()时或者自身析构的时候该对象就会被释放,即对象的持有者负责管理对象的retain和release,从而实现谁持有,谁管理,谁释放的原则。

*** cocos2d-x内存管理CCObject与autorelease深入分析

引用计数器是一种内存管理方式。通过一个无符号的成员变量计算当前有多少使用者在使用本内存。每次外部对象使用本内存时计数器加1,使用完要释放本内存时计数器减1,当计数器减为0时才真正进行占用内存释放。这样做可以实现在多个使用者使用一块内存时,只有当所有的使用者都确定不再使用这块内存的时候才进行内存的释放。避免了在还有使用者在使用内存时提前释放内存而导致的程序崩溃。

有兴趣的同学可以看引擎的源编,在源码中我们看到CCObject做的工作比较简单,它主要就是有两个功能。一个是通过引用计数交给内存管理器进行内存管理。另一个就是通过脚本ID访问相应的脚本。脚本的分析暂时不探讨,我们暂时只把内存管理的事情搞明白。我们来重点看一下autorelease函数的意义,顾名思义,“自动释放”。也就是说调用此函数则当前CCObject实例对象不需要用户在外部去手动调用release进行内存的释放工作。我们上面已经知道它通过引用计数来处理在什么时候内存释放,那么Cocos2d-x是怎么做到的?

在autorelease函数中有这么一句:CCPoolManager::sharedPoolManager()->addObject(this);

CCPoolManager代表了内存管理器。此句调用CCPoolManager的实例对象的addObject函数将当前CCObject实例对象的指针交给内存管理器,内存管理器负责管理CCAutoReleasePool,CCAutoReleasePool中加入的就是被自动管理的对象。

下面来看一下内存管理器的原理:

CCMutableArray是一个CCObject指针容器类,它内部通过使用STL的vector容器来存储CCObject指针。在加入一个新CCObject时对其引用计数器加1,在移除CCObject时对其引用计数器减1。有兴趣的同学可以自行打开CCMutableArray.h及cpp文件进行查看。

那么上面的介绍大家应该已经有了一个比较清楚的了解了, 最后再总结一下:Cocos2d-x提供了一个内存管理器类CCPoolManager,它有一个容器,而这个容器是用来存放了一些容器管理类CCAutoreleasePool的实例对象的。需要自动进行内存释放的CCObject实例对象会把其指针存放在容器管理类CCAutoreleasePool的实例对象中的m_pManagedObjectArray容器里。所有存在其中的CCObject实例对象在进行释放操作时通过使用计数器来进行判断在何时真正delete内存。

时间: 2024-11-10 06:57:13

Cocos2d-x内存管理的相关文章

cocos2d 内存管理

-- 不要怕,勇敢的迈出第一步,加油!!!!!-- 此章介绍cocos2d 中的内存管理 1. cocos2d 中的所有Node类都继承于Ref,Ref中有引用计数的概念,如下: class TestRef  : public Ref { public: TestRef() {} virtual ~TestRef() {} }; new TestRef -- 这时class Ref 中的_referenceCount = 1 retain -- _referenceCount++ release

Cocos2d之&ldquo;引用计数&rdquo;内存管理机制实现解析

一.引言 本文主要分析cocos2d游戏开发引擎的引用计数内存管理技术的实现原理.建议读者在阅读本文之前阅读笔者之前一篇介绍如何使用cocos2d内存管理技术的文章--<Cocos2d之Ref类与内存管理使用详解>. 二.相关概念 引用计数 引用计数是计算机编程语言的一种内存管理技术,是指将资源(对象.内存或者磁盘空间等)的被引用计数保存起来,当引用计数变为零时就将资源释放的过程.使用引用计数技术可以实现自动内存管理的目的. 当实例化一个类时,对象的引用计数为1,在其他对象需要持有这个对象时,

cocos2d 内存管理机制

简单做下笔记,等有更深的理解时再补充. Cocos2d内存管理的基本原理是对象内存引用计数.当声明定义一个对象时,会在堆上为这个对象分配内存,并且有一个变量m_uReference专门用于记录该对象被引用了多少次. 内存引用计数的原理就是,当该对象被引用时m_uReference++,当该对象被取消引用时m_uReference--,若果m_uReference==0时,该对象就会被释放. 有了基本概念后,就不得不提及两个重要的函数--retain()和release().这两个函数是干什么用的

Cocos2d之Ref类与内存管理使用详解

一.简介 用C++和JAVA编写过程序的朋友一定会为两种语言不同的内存管理机制懊恼.JAVA程序运行在JVM之上,由JVM自动实现内存管理,开发者只管申请内存而不用手动释放内存.当JAVA中对象没有被任何引用变量(类似于C和C++的指针)引用时,JVM会将对象释放掉.C++和C一样,是编译后能够直接被操作系统执行的语言,没有虚拟机负责其内存管理,因此需要在程序中管理内存.本文主要介绍如何使用cocos2d提供的内存管理机制. Cocos2d-x借鉴了“引用计数”思想,实现了一定程度上的自动内存管

cocos2d内存管理

设想如下场景, 这是一个典型的内存合理分配的场景: 在一帧内, 有若干个函数, 每个函数都会创建一系列的精灵, 每个精灵都不同, 都会占用一定的内存, 精灵的总数可能会有1000个, 而一个函数只会创建10个精灵这样, 创建的精灵只会在这个函数中使用, 大致代码如下: for(int i = 0; i < 10; i++) { Sprite* s = Sprite::create(); //-- doSomething -- } 这样做会造成内存泄露吗? 答案是当然不会, 但是这样会造成一帧内的

cocos2dx[3.2](24)——内存管理机制

[参考] http://zh.wikipedia.org/wiki/引用计数 (引用计数--维基百科) http://cn.cocos2d-x.org/tutorial/show?id=2300 (引用计数和自动释放池) http://cn.cocos2d-x.org/tutorial/show?id=1331 (内存管理--绕不过去的坎) http://blog.csdn.net/legendof1991/article/details/23360131 (内存优化) https://gith

cocos2dx内存管理

cocos2dx基于引用计数管理内存,所有继承自CCObject的对象都将获得引用计数的能力,可通过调用retain成员函数用于引用计数值,调用release减少引用计数值,当计数值减为0时销毁对象. cocos2dx的对象管理是树形结构的,可通过调用父亲节点的addChild成员函数将一个子节点对象添加到父节点中,当子节点被添加到父亲节点中,子节点的引用计数值加1,如果通过removeChild将子节点从父节点中移除子节点的引用计数值减1.当父节点被销毁时,会遍历其所有的子节点,将其子节点的引

cocos2d-x 源码分析 : Ref (CCObject) 源码分析 cocos2d-x内存管理策略

源码版本来自3.x,转载请注明 cocos2d-x 源码分析总目录: http://blog.csdn.net/u011225840/article/details/31743129 1.Ref,AutoreleasePool,PoolManager Ref中包含了一个叫referenceCount的引用计数,当一个Ref类的变量被new的时候,其referenceCount的引用计数被置为1. 其中有三个重要的操作,retain,release,autorelease,下面源码分析时会详细说明

8、Cocos2dx 3.0游戏开发找小三之3.0版本的内存管理

重开发者的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27693365 复杂的内存管理 移动设备上的硬件资源十分有限,内存尤为宝贵,开发者必须十分慎重地利用内存,避免不必要的消耗,更要防止内存泄漏. 基于 Cocos2d-iPhone 的 Objective-C风格的内存管理是 Cocos2d-x 的一个特色. 把 Objective-C 的内存管理方式引入 C++,使得游戏开发的内存管理难度下降了个层次.

cocos2d-x内存管理(见解)

cocos2d-x 延续了cocos2d 和OC的引用计数的内存管理机制! 下面我们来看看CCDriectro类 CCPoolManager::sharedPoolManager()->push(); 基础:我们要先熟悉  release  释放该内存! CCPoint *temp = new CCPoint(controlPoint.x, controlPoint.y); m_pControlPoints->addObject(temp); temp->release(); autor