cocos2d-x內存管理機制解析(二)

轉自:http://blog.csdn.net/a7833756/article/details/7632199


前一篇我們講到cocos2d-x裏的內存管理機制,以及引擎中的自動內存管理機制。一個被自動管理的對象從new出來之後到被放到autoreleasepool那麼接下來,對象是如何被引擎自動delete掉的呢?首先我們要知道,cocos2d-x的引擎線程是單線程的,它不停的調用voidCCDisplayLinkDirector::mainLoop(void)來繪製當前的Scene ,同時對一些自動釋放的對象進行管理。我們先到一個cocos2d-x項目的main()函數裏面:


這裏調用了一個run()方法,我們跟蹤進去:


Run方法有個while(1)循環,不斷的調用mainLoop(void)方法,來完成界面渲染和對象釋放,我們進mainLoop():


於是我們看到了引擎對自動管理的對象進行釋放的操作。它調用的,是CCPoolManager的pop()方法,我們去看看這個pop()方法:


如代碼裏面所示,m_pReleasePoolStack就是之前提到的當前內存池,也就是內存池管理者裏面那個內存池堆棧的棧頂的那個內存池,對其進行clear()操作,記住,在clear()之前,被放置在自動管理池內的對象的引用次數都是爲1的(依然只考慮對象被new出來之後馬上autorelease()操作並且在其他地方不進行retain()),那麼進行clear()操作時:


CCAutoreleasePool會做這樣兩件事情,首先會把池中所有對象的被管理狀態置爲false,表示對象已經不再處於自動管理狀態,然後清除管理池中所有的對象引用:


在這一過程中,會調用每個對象的release()方法,這樣,我們算一下,之前對象的引用次數爲1,那麼在這裏進行一次release之後,引用爲0,就會執行delete操作,這樣一來,這個被管理的對象就被成功釋放掉了。

下面我們來寫個小demo驗證一下這個過程:

New一個對象:


s的引用次數爲1,被管理狀態爲false:


對其進行autorelease()


s的引用依然爲1,被管理狀態爲true:


然後進行一次retain()操作:


引用變爲2


接下來刷下一幀,刷完後我們再看o對象,發現其被管理狀態變爲false,引用變成1了,這說明如果我們之前沒有手動執行過retain(),這個對象已經被引擎給回收掉了。


這樣一來,驗證了引擎的自動回收機制,我們可以在retain()後面release()一次,來看看對象o被delete後的狀態:


發現其內部的數據都變成隨機數值了,也就是對象已經被清除了。

 

最後我來做個簡單的總結

Cocos2d-x中,採用引用計數的方式進行內存管理,誰需要引用這個對象,就對其retain()一次,同時在不需要它的時候,就要對其進行release()操作,這一點在引擎很多地方有示例,例如CCNode進行addchild()操作時,會對child進行retain()表示對其引用:


而在removeChild()的時候會對其進行release()操作


第二點是對象的autorelease()操作,該操作的效果是對象在當前這一幀被new出來之後,在下一幀之前沒有被執行retain()(例如被add到某個CCMutableArray,或者被一個父Node作爲子節點,也可以是我們手動retain()),那麼這個對象在下一幀就會被引擎給delete掉,那麼有時候出現的空指針錯誤,可能就來源於此。還有的時候,是在自己手動retain()後放入autorelease池,這樣引擎只能將對象的引用減一,而不能delete掉,從而造成內存泄露。最後說一下,本人也是剛開始學習c++和cocos2d-x,寫這篇博客與大家分享一下自己的心得,也是希望能幫到一部分對cocos2d內存管理有困惑的朋友,讓大家能共同學習進步,同時對我所講到的不合理的地方,希望各位大牛能夠指出,感謝閱讀!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章