Cocos2d内存管理分析
2014-10-21 22:23
375 查看
1、 UML图
2、 说明
步骤1:cocos2d在初始化的时候调用CCDirector中的init方法,在init方法中:
// create autorelease pool
CCPoolManager::sharedPoolManager()->push();
即创建了一个内存自动回收池管理器,并调用push方法
步骤2:
void CCPoolManager::push()
{
CCAutoreleasePool* pPool =new CCAutoreleasePool(); //ref = 1
m_pCurReleasePool = pPool;
m_pReleasePoolStack->addObject(pPool); //ref = 2
pPool->release(); //ref =1
}
在push方法中主要创建了一个内存自动回收池,并把其设为当前的内存自动回收池,加入到内存自动回收池管理器中,并release该内存自动回收池,但由于addObject会把该内存回收池的引用加1,所以在这儿并不会真正的释放该对象。而该对象会在CCPoolManager::pop()方法和CCPoolManager的析构函数中被释放。
下面就以CCSprite为例,看Cocosdx是怎么管理精灵的内存的。
步骤5:
CCSpirte::create()方法,该方法也是cocos2dx中最常用的工厂方法,这样创建的对象是不需要用户去管理内存的,但这样会增加额外的内存开销,并影响效率。所以如果有需要,可以自己管理内存。
CCSprite*CCSprite::create()
{
CCSprite *pSprite = newCCSprite();
if (pSprite &&pSprite->init())
{
pSprite->autorelease();
return pSprite;
}
CC_SAFE_DELETE(pSprite);
return NULL;
}
CCSprite::create方法中主要是new一个对象,并调用init()初始化,并调用autorelease(),把该对象加入到自动内存回收池中。下面看看CCObject::autorelease的实现。
CCObject*CCObject::autorelease(void)
{
CCPoolManager::sharedPoolManager()->addObject(this);
return this;
}
只是转调了一把。CCPoolManager::addObject实现如下:
void CCPoolManager::addObject(CCObject* pObject)
{
getCurReleasePool()->addObject(pObject);
}
getCurReleasePool即获取步骤2中创建的CCAutoreleasePool对象,并调用addObject方法
void CCAutoreleasePool::addObject(CCObject* pObject)
{
m_pManagedObjectArray->addObject(pObject);
CCAssert(pObject->m_uReference > 1, "reference count shouldbe greater than 1");
++(pObject->m_uAutoReleaseCount);
pObject->release(); //no ref count, in this case autorelease pool added.
}
pManagedObjectArray是一个CCArray对象,通过该方法中的addObject把对象加入到内存自动回收池中,并让该对象的引用计数加1。并让该对象的自动引用计数加1,方便后续对该对象的管理。对对象引用计数的操作是在ccCArray:: ccArrayAppendObject中实现的。CCAutoreleasePool::addObject中先是让该对象的引用计数加1,后又调用release方法,让该对象的引用计数减一,所以,CCSprite对象的引用计数还是为1,如果现在不对CCSprite对象做其他的操作,那么,该对象在下一帧的时候就会被自动回收。为什么呢,我们看看CCDisplayLinkDirector::mainLoop(void)方法,即游戏主循环。
voidCCDisplayLinkDirector::mainLoop(void)
{
if(m_bPurgeDirecotorInNextLoop)
{
m_bPurgeDirecotorInNextLoop = false;
purgeDirector();
}
else if (! m_bInvalid)
{
drawScene();
// release theobjects
CCPoolManager::sharedPoolManager()->pop();
}
}
第一个条件语句会在该游戏结束的时候才会满足该条件,主要是去回收资源。
第二个条件只有在调用stopAnimation后才不会满足,所以:
drawScene主要是去绘制当前场景,而pop就是对内存的回收。
voidCCPoolManager::pop()
{
if (! m_pCurReleasePool)
{
return;
}
int nCount =m_pReleasePoolStack->count();
m_pCurReleasePool->clear();
if(nCount > 1)
{
m_pRel
ae71
easePoolStack->removeObjectAtIndex(nCount-1);
// if(nCount > 1)
// {
// m_pCurReleasePool = m_pReleasePoolStack->objectAtIndex(nCount - 2);
// return;
// }
m_pCurReleasePool =(CCAutoreleasePool*)m_pReleasePoolStack->objectAtIndex(nCount - 2);
}
/*m_pCurReleasePool =NULL;*/
}
其对内存的回收是通过clear方法去实现的
void CCAutoreleasePool::clear()
{
if(m_pManagedObjectArray->count() > 0)
{
//CCAutoreleasePool*pReleasePool;
#ifdef _DEBUG
int nIndex =m_pManagedObjectArray->count() - 1;
#endif
CCObject* pObj = NULL;
CCARRAY_FOREACH_REVERSE(m_pManagedObjectArray, pObj)
{
if(!pObj)
break;
--(pObj->m_uAutoReleaseCount);
//(*it)->release();
//delete (*it);
#ifdef _DEBUG
nIndex--;
#endif
}
m_pManagedObjectArray-> removeAllObjects ();
}
}
CCARRAY_FOREACH_REVERSE是一个for循环的宏定义,在这个for循环中会把当前内存回收池中所有的对象的uAutoReleaseCount减一,而真正去release这些对象是在removeAllObjects中去实现的,pManagedObjectArray是一个CCArray对象,所以调用的是CCArray:: removeAllObjects方法,该方法会调用ccCArray中的
void ccArrayRemoveAllObjects(ccArray *arr)
{
while( arr->num > 0 )
{
(arr->arr[--arr->num])->release();
}
}
该方法会遍历该对象中所有的节点,并调用每个节点的 release方法,下面我们再看看release方法的实现,该方法是在CCObject中
void CCObject::release(void)
{
CCAssert(m_uReference >0, "reference count should greater than 0");
--m_uReference;
if (m_uReference == 0)
{
delete this;
}
}
release方法会把该对象的引用计数减一,然后判断该对象的引用计数是否为0,如果该对象的引用计数为0,就删除该对象,这也是智能指针常用的做法。
所以刚刚我们用工厂方法创建的CCSprite对象,如果不对该对象进行其他操作,那么在游戏的下一次循环就会被自动回收。
因此我们在创建一个CCSprite对象后,都会把该对象加入到Layer中去,以防止该对象被自动回收,CCSprite::addChild会调用到CCNode::addChild,然后调用CCNode::insertChild,该方法中会通过ccCArray::ccArrayAppendObjectWithResize方法,把要添加的对象的引用计数加一。
相关文章推荐
- cocos2d-x与ios内存管理分析(在游戏中减少内存压力)
- cocos2d-x与ios内存管理分析(在游戏中减少内存压力)
- Cocos2d-x与iOS内存管理分析
- Cocos2d-x与ios内存管理分析(在游戏中减少内存压力)
- cocos2d-x 源代码分析 : Ref (CCObject) 源代码分析 cocos2d-x内存管理策略
- cocos2d-x与ios内存管理分析(在游戏中减少内存压力)
- cocos2d-x与ios内存管理分析(在游戏中减少内存压力)
- cocos2d-x V3.x内存管理分析
- Cocos2d-X3.0 刨根问底(四)----- 内存管理源码分析
- 【Cocos2d-x源码分析】 Cocos2d-x内存管理解析
- cocos2d-x与ios内存管理分析(在游戏中减少内存压力)_(转)
- cocos2d-x与ios内存管理分析(在游戏中减少内存压力)
- cocos2d-x与ios内存管理分析(在游戏中减少内存压力)
- cocos2d-x V3.x内存管理分析
- cocos2d-x 源码分析 : Ref (CCObject) 源码分析 cocos2d-x内存管理策略
- cocos2d-x与ios内存管理分析(在游戏中减少内存压力)
- cocos2d-x与ios内存管理分析
- Cocos2d-X3.0 刨根问底(四)----- 内存管理源码分析
- Cocos2d-X3.0 刨根问底(四)----- 内存管理源码分析(转)
- Cocos2d-x V3.x内存管理分析