cocos2d-x的内存管理

本文详细介绍了Cocos2d-x中2D内存管理机制,包括引用计数器管理的核心概念、节点管理流程及常见操作的影响。同时探讨了如何避免内存溢出和内存泄漏等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

终于下定决心去写点东西,主要是最近学习的效率越来越低,很多东西都是在:遇到问题——查资料——解决问题——同样的问题——忘记了——重新查资料,这个循环中反复,所以决心去写些东西。

这篇只是写入了我对2d内存管理的一些理解以及一些处理,主要是工作中遇到的,目的是整理一下自己所学,我会尽力保证正确性,但是限于水平,可能会有错误的理解和错误的描述,仅供参考,欢迎指正。

cocos2d-x的内存管理机制是引用计数器管理,基本原理是:cocos2d节点都继承自 CCObject(3.0版本更名为Ref),基本的节点创建推荐使用 create方法(似乎在3.0以后,官方有些偏向于逐渐推荐c++本身的new方法来创建),总之在create方法中,会new一个节点对象,并调用节点对象的init(),以及autoRelease。节点自身的初始化通常会在节点类的init()函数中实现,节点的初始retainCount(引用值)为1,而autoRelease会将节点指针加入自动释放池中,从而保证在这帧结束之前,节点对象始终不被销毁,而在一帧结束的时候,cocos2d会将自动释放池中所有节点的retainCount减1,如果减一之后的retainCount为0,则删除这个节点。遍历过整个自动释放池之后,2d就将整个释放池清空。

内存管理的所有核心就在引用计数器管理上了,我目前所知的会有以下的几种操作会影响内存的retainCount。

1.autoRelease:调用节点的autoRelease函数会将节点加入自动释放池中,之后在当前帧结束之后,自动释放池会将节点的retainCount减1并判断是否为0,如果为0将会删除。具体的操作是自动释放池中有一个vector,每次调用autoRelease,vector会将节点的指针push_back到vector中,当前帧结束后自动释放池遍历这个vector并调用vector中每个对象的Release函数。


2.release retain函数。这两个函数通常是一对使用的,类似于push pop。retain会将节点的retainCount + 1 。Release会将retainCount - 1并在减一后判断retainCount是否为0,如果为0,删除节点。当然cocos秉承了一个很好的设计原则,即所有操作retainCount的方法只调用这两个函数(Release retain)。


3.addChild removeChild 这两个也是一对,addChild向节点树上添加会将retainCount + 1 ,removeChild从节点树上删除会将retainCount - 1。

4.action 这个可能是cocos很隐蔽的一处,我也是过了一段时间才知道原来一个节点当它runAction 或者是stopAction也会影响节点的retainCount,由于这点处理不好导致了一些内存泄漏,当然通常是不需要太关注这个的,因为当节点从节点树上移除时,会在onexit()中停掉它所有的action,但是由于之前不太熟悉,对滚动条:tableview的修改导致了问题。

以上部分基本上就是我所知的cocos的节点管理,但是很重要的一点是,当你删除一个node时,通常内存并不会下降(文字除外),因为在游戏中内存占用最多的部分是纹理,而纹理并不会随着节点的释放而释放。它们被储存在textureCache中,也就是cocos的纹理缓存,直到你手动调用方法 : removeUnusedTextures 或者removeAllTextures才会进行纹理释放。(当然其实大量的字符串也会占用内存,并且在cocos2d-x 2.0版本中存在bug 当你读取文件一定会泄漏内存,当然这个问题在3.0中得到了修复,都是血泪啊...)

 

归根结底,内存问题无非就是内存加载溢出,以及内存泄漏。

 

先说内存加载中溢出,cocos的纹理加载会在加载的那一帧瞬间膨胀2倍,所以当内存中本身已经缓存了过多的纹理时,再加载一个大场景,就容易当场跪掉。实话说这一块的机制我并不是特别的了解,我通常的解决方法是在点击事件中先调用removeUnusedTextures()然后加载界面,另外,借用前辈的经验:千万不要在memoryWaring中调用removeUnusedTextures()。会导致反复加载,从而使界面的加载变得特别慢。

 

我所遇到的内存泄漏问题通常也就是节点被非正常retain,导致节点以及其上面的子节点始终占用图片资源,纹理缓存无法释放,最终内存泄漏。原因可能千千万,不过泄漏倒是很容易查明的,getCachedTextureInfo(),就可以搞定。该函数是将cocos缓存的所有图片纹理的引用值,比如你在其中一个界面,调用该函数,然后发现本来不在显示,你认为已经移除的界面的一张背景图的retainCount大于1,那么起码这张背景图的节点是被retain了,逐级向上查就好。

当然c++本身的内存管理归程序的机制就容易导致内存泄漏,但是cocos的工厂模式其实已经避免了绝大多数new了之后忘记delete的情况,而解决了纹理的内存泄漏之后通常其他的问题也不足为患了。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值