今天想探索一下cocos2dx的記憶體管理,我們就先從ccobject開始吧
class cc_dll ccobject : publiccccopying
;
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()函式,我們來看看該函式主要做了哪些工作?
voidccpoolmanager::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?
voidccautoreleasepool::clear()
//(*it)->release();
//delete (*it);
#ifdef _debug
nindex--;
#endif
} m_pmanagedobjectarray->removeallobjects();
}}
以上函式主要做的工作是:1、將內部的所有元素的自動釋放引用m_uautoreleasecount減一。2、清除內部的所有元素。看到這裡我很詫異:為什麼要清除所有的元素呢?難道不是清除那些無效的物件例項嗎?緊接著看下面的函式看他如何removeallobjects。
voidccarray::removeallobjects()
void ccarrayremoveallobjects(ccarray *arr)
}
以上函式其實就是將陣列內部的所有元素release一下,並將元素個數減為0。到這裡整個物件建立—新增到自動釋放池—幀尾的釋放的過程就完了,我一開始很是納悶,假如我有定義了乙個類如下:
class a : publicccnode
;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, inttag)
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...