cocos2dx記憶體管理

2022-09-07 01:06:16 字數 3972 閱讀 7643

今天想探索一下cocos2dx的記憶體管理,我們就先從ccobject開始吧

class cc_dll ccobject : public

cccopying

;

friend

class

ccautoreleasepool;

unsigned

intgetautoreleasecount();

};

以上是ccobject的定義,可以看出ccobject主要有兩個保護成員:m_ureference和m_uautoreleasecount,這個兩個成員到底有什麼用呢?讓我們一**竟,首先我們來看一下ccobject的建構函式:

ccobject::ccobject(void

): m_nluaid(0)

, m_ureference(

1) //

when the object is created, the reference count of it is 1

, m_uautoreleasecount(0

)

從建構函式我麼可以看出m_ureference初始化為1,m_uautoreleasecount初始化為0,另外ccobject維護了乙個靜態無符號整型變數:uobjectcount來記錄ccobject例項的總數目。然後我們來看一下release()和retain()函式:

void ccobject::release(void

) ccassert(m_ureference > 0, "

reference count should greater than 0");

--m_ureference;

if (m_ureference == 0

)

}

由release()函式可以看到每執行一次release(),m_ureference自減一,只有當m_ureference為零時ccobject物件才會被釋放;

void ccobject::retain(void

) ccassert(m_ureference > 0, "

reference count should greater than 0");

++m_ureference;

}

retain()函式和release()函式功能正好相反,每呼叫一次retain(),m_ureference會自增一;接下來我們再來看看autorelease()函式:

ccobject* ccobject::autorelease(void

)void ccpoolmanager::addobject(ccobject*pobject)

此處涉及到乙個ccpoolmanager類,該類內部有乙個ccautoreleasepool型別的棧,而ccpoolmanager又是什麼呢?其實ccpoolmanager就是乙個ccarray乙個可增長的陣列,我們來看看他得addobject(ccobject* pobject)函式:

void ccautoreleasepool::addobject(ccobject*pobject)

在除錯的時候我們會發現ccobject在release()時他的m_ureference為2,也就避免了被釋放,其實該物件例項在新增到自動釋放池(ccautoreleasepool)的時候retain了一下;我們來驗證一下,來看看下面的幾個函式:

void ccarray::addobject(ccobject* object)/*

*/)/**/

)

接下來我們來看一下cocos2dx如何銷毀那些無效的物件例項,以下是整個程式的主迴圈:

void ccdisplaylinkdirector::mainloop(void

)

else

if (!m_binvalid)

}

由上面函式可知coco2dx在每一幀的幀尾會呼叫自動釋放記憶體池的管理者—ccpoolmanager的pop()函式,我們來看看該函式主要做了哪些工作?

void

ccpoolmanager::pop()

int ncount = m_preleasepoolstack->count();

m_pcurreleasepool->clear();

if(ncount > 1

)

m_pcurreleasepool = (ccautoreleasepool*)m_preleasepoolstack->objectatindex(ncount - 2

); }

/*m_pcurreleasepool = null;

*/}

主要做的就兩點:1、清除當前的自動釋放池,2、更新當前自動釋放池指標;我們來看看他是如何clear?

void

ccautoreleasepool::clear()

//(*it)->release();

//delete (*it);

#ifdef _debug

nindex--;

#endif

} m_pmanagedobjectarray->removeallobjects();

}}

以上函式主要做的工作是:1、將內部的所有元素的自動釋放引用m_uautoreleasecount減一。2、清除內部的所有元素。看到這裡我很詫異:為什麼要清除所有的元素呢?難道不是清除那些無效的物件例項嗎?緊接著看下面的函式看他如何removeallobjects。

void

ccarray::removeallobjects()

void ccarrayremoveallobjects(ccarray *arr)

}

以上函式其實就是將陣列內部的所有元素release一下,並將元素個數減為0。到這裡整個物件建立—新增到自動釋放池—幀尾的釋放的過程就完了,我一開始很是納悶,假如我有定義了乙個類如下:

class a  : public

ccnode

;bool

a::init()

實際上到下一幀的時候,m_psprite2所指向的記憶體已經無效,m_sprite1仍然有效。上面的過程是如何做到的呢?只有這種情況才能解釋:m_psprite1和m_psprite2在create的時候加入到了自動釋放池被監視,而m_psprite1再加入到父節點時retain了一下,才不會在幀尾release的時候被釋放掉。我們來驗證一下ccnode::addchild(…)(引數就不寫了):

void ccnode::addchild(ccnode *child, int zorder, int

tag)

this->insertchild(child, zorder);

child->m_ntag =tag;

child->setparent(this

); child->setorderofarrival(s_globalorderofarrival++);

if( m_brunning )

}

發現沒有retain,繼續看insertchild函式:

void ccnode::insertchild(ccnode* child, int

z)

))

終於發現了retain。

總結:當乙個ccobject例項被建立:

1、若被autorelease(),那麼在當前幀的幀尾會被release()一次(注意僅僅一次,以後就會被移除監視),若之前加入到了父節點中那麼幀尾的release()時會避免釋放,反之則會被無情的釋放掉。如果沒有加入到父節點又想想擁有該物件,那麼需要自己retain();

2、若沒有autorelease(),那麼這個例項就需要自己來管理。

cocos2dx 記憶體管理

記憶體管理中經常遇到的問題 記憶體洩露,記憶體溢位。在cocos2dx中用的是引用計數和自動釋放池的技術,由於熟悉objective c語言,所以對這兩個概念不會很陌生。一 引用計數 引用計數是自動記憶體管理的基礎 在物件裡增加乙個引用計數,當外部引用增加時,計數器加1,當外部引用消失時,計數器減1...

cocos2d x 記憶體管理

呼叫了autorelease的物件,將會在自動 池釋放的時候被釋放一次。因為這個操作發生在 mainloop drawscene 後,這時候遊戲中所有的邏輯已經執行完畢,正是釋放無效資源的最佳時機。所以乙個物件被create後,將被放進pool中,其ref 數為1,當遊戲整個邏輯跑完,如果沒有增加r...

cocos2dx 記憶體管理

我們知道,cocos2dx中使用了引用計數的方式去管理記憶體,不需要我們手動delete的去釋放記憶體。那麼cocos2dx中是怎麼實現引用計數的記憶體管理方式的呢?cocos2dx中的記憶體管理用到了兩個工具 引用計數器 ref 自動 池 autoreleasepool 引用計數器 ref ref...