} } }

    cocos2d-x内存经管机制

    添加时间:2013-6-28 点击量:

    cocos2d-x源于cocos2d-iphone,为了与Objective-c一致,cocos2d-x也采取了引用计数与主动收受接管的内存经管机制。


    要实际主动内存收受接管,需持续于cocos2d-x的根类CCObject。当然主动开释会影响机能,解决规划看最后。



    cocos2d-x中有很多静态工厂办法,例如以create开首的,这些静态工厂办法创建的对象都应用的autorelease,试想若是不消autorelease,


    CCObject create(){CCObject ret = new CCObject(); return ret;}


    此时函数内的引用在函数停止时就停止了,然则对方没有被开释,若是返回的ret没有被用户引用或者开释,那么就造成了内存泄漏。所以参加autorelease是个不错的解决办法。



    看看CCObject的这两个字段和办法:



    protected:
    
    // 引用计数
    unsigned int m_uReference;
    // 主动开释次数 以前是bool m_bManaged;标识是否采取主动开释
    unsigned int m_uAutoReleaseCount;
    public:
    void release(void);
    void retain(void);
    CCObject
    autorelease(void);
    unsigned
    int retainCount(void);


    有这么一个原则:谁引用谁retain和release,对象传值时先retain再release(避免本身给本身传值时,先release可能会开释对象),调用release办法,当引用计数为0时,就会此对象。


    内存经管autorelease是怎么实现的呢,进入autorelease看到调用了下面这个函数:


    oolManager::sharedPoolManager()->addObject(this);将对象参加收受接管池



    void CCAutoreleasePool::addObject(CCObject pObject)
    
    {
    m_pManagedObjectArray
    ->addObject(pObject);

    CCAssert(pObject
    ->m_uReference > 1reference count should be greater than 1);
    ++(pObject->m_uAutoReleaseCount);
    pObject
    ->release(); // no ref count, in this case autorelease pool added.
    }


    函数中将对象参加经管数组中,再对主动开释计数+1,然后release使引用计数-1。


    当create一个对象时,new使引用计数为1,调用autorelease后,参加收受接管池,然后release引用计数-1。那么此时引用计数为0吗?


    答案必然不是,若是为0,此时该对象就会被。cocos2d-x中的数据布局转为这种内存经管设置,如CCArray,当对array调用addObject时,就会调用retain使引用计数加1,当array调用removeObject时就会release。那么当参加收受接管池后,此时的这个引用归收受接管池所有,当一帧停止开释收受接管池的时辰,收受接管池中的所有对象都邑调用release。若是此时没有其他对象引用该对象,则该对象会被删除。



    来看看主轮回mainLoop中的调用:



        if (m_bPurgeDirecotorInNextLoop)
    
    {
    m_bPurgeDirecotorInNextLoop
    = false;
    purgeDirector();
    }
    else if (! m_bInvalid)
    {
    drawScene();

    // release the objects
    oolManager::sharedPoolManager()->pop();
    }


    每一帧停止调用sharedPoolManager()->pop()此时栈顶的收受接管池就被开释,此时池中的所有对象都邑被release,若是没有其它的对象(场景、层、数组等)在引用他们,就会被。而一帧开端又建树收受接管池sharedPoolManager()->push()。



    可以看出每一帧收受接管池都要建树、删除,并且添加对象进入收受接管池,那么机能方面当然会受到影响,当收受接管池中对象很多时,发挥解析得很明显。


    那么解决办法1:机能请求高的景象下不要随便马虎应用主动收受接管池。



    办法2:手动开释并创建一个收受接管池



    oolManager::shardPoolManager()->push();
    
    forint i=0; i!=n; ++i)
    {
    objArray[i]
    ->autorelease();
    }
    oolManager::shardPoolManager()
    ->pop();


    如许就不会让主动开释的对象集中在一帧停止的时辰。



    读书,不要想着实用,更不要有功利心。读书只为了自身的修养。邂逅一本好书如同邂逅一位知己,邂逅一个完美之人。有时心生敬意,有时怦然心动。仿佛你心底埋藏多年的话,作者替你说了出来,你们在时光深处倾心相遇的一瞬间,情投意合,心旷神怡。
    分享到: