Cocos2d x 記憶體管理

2022-08-16 15:45:10 字數 2466 閱讀 1190

一、記憶體管理機制

cocos2d-x是一套基於c++的引擎,c++的記憶體機制,如果採用new關鍵字宣告乙個物件而沒有手動delete掉,那麼申請的記憶體就不會被**,進而造成記憶體洩露。cocos2d-x是採用引用計數的方式管理記憶體,基本的原則就是當構造乙個物件時,引用計數為1,每次進行retain操作的時候,引用計數加1,每次進行release操作的時候,引用計數減1,當乙個物件的引用計數為0時,就將這個物件delete掉,詳細的機制可以看ccobject的原始碼。

那麼當你在cocos2d-x中new乙個物件,引擎又是怎麼幫你管理的呢?cocos2d-x自身的自動記憶體管理機制其實是不推薦使用的,因為在遊戲開發的過程中會出現很多的引用計數問題,它的大概的管理流程是這樣的,當你create乙個物件時,就會自動對這個物件進行一次autorelease的操作,這個autorelease做了很多的事,簡單地說就是,執行了autorelease的物件就表明這個物件處於自動管理的狀態,會在記憶體管理池ccpoolmanager中新增這個物件,並且在自動釋放記憶體池ccautoreleasepool的堆疊中申請一塊記憶體池放入這個物件。之後在不需要用的時候引擎會自動delete掉它,引擎是用單一的執行緒來進行場景的繪製,通過不斷呼叫mainloop這個函式,這個函式除了進行場景的繪製,也會呼叫ccpoolmanger函式的pop方法對自動管理的物件進行釋放操作,pop方法會對ccautoreleasepool堆疊棧頂的記憶體池進行操作,將池內的物件標記為非自動管理狀態,並進行一次release操作,清除引用計數為1的物件,然後取出前乙個入棧的記憶體池等待下一輪的釋放。那麼這種機制有時就會出現錯誤,如果我們沒有進行retain操作,new出來的物件可能在下一幀就已經release掉了,出現空指標的錯誤,而如果我們自己進行手動的retain操作的話,一次的clear操作只能將引用計數減1,無法delete掉物件,又會造成記憶體洩露,所以很不推薦使用自帶的自動記憶體管理。cocos2d-x中存在大量的靜態工廠方法,這些方法全都對this指標呼叫了autorelease方法,通過靜態工廠來生成物件可以簡化**。有興趣的同學可以自己寫乙個記憶體管理的控制項哦!難度不大就看效率咯!

二、的快取和載入方式

在ios上,所有的都會自動縮放到2的n次方,這就意味著一張1024*1025大小的和1024*2048的占用的記憶體是一樣的,而占用的記憶體可以由公式:長*寬*4來計算得到,所以一張1024*1024的占用的記憶體大小是1024*1024*4,也就是4m,ios上最大支援的尺寸是2048*2048。

在cocos2d-x中進行載入時,如果是第一次載入就要把載入到快取,然後從快取中載入,如果快取中已經有了,就直接從快取中載入。

的快取有兩種型別,一種是cctexturecache,另一種是ccspriteframecache。

第一種是普通的載入快取,一般直接載入的都會放到這個快取裡面,這是乙個會經常要用到的快取,所以又必要熟悉它的一些函式,要知道這個快取如果不手動釋放,它是會一直占用記憶體的,它有很多函式介面,都是為了方便進行記憶體管理的,例如removealltextures()(清空所有的快取),removeunusedtextures()(清除沒用的快取),dumpcachedtextureinfo()(輸出快取的資訊)等等。我自己針對這個cache的管理寫了乙個類,不過感覺在很大資料量的時候效率可能會比較低,還有待改進。

那麼這兩種載入方式對記憶體有什麼具體的影響呢?

首先為了方便我們得到記憶體的具體資訊,我們要使用檢測記憶體洩露的工具,我用的是vld,具體的使用方法我在另一篇博文中有分享。

以載入一張1024*1024的為例。

如果使用ccsprite *psprite = ccsprite::spritewithfile("background.png");可以看到記憶體增加了4m左右的大小,如果對這張進行渲染的話,例如使用addchild(psprite);,記憶體又會增加4m,所以一張的載入實際上占用了2倍的記憶體。

如果使用ccspriteframecache::sharedspriteframecache->addspriteframeswithfile("p.plist");,假設大圖的大小為2048*2048,那麼記憶體直接增加了16m,此時想要載入大圖中的一張小圖,記憶體又會增加16m,不過以後再使用大圖中的就不會增加記憶體了。

三、常見的記憶體管理的方法:

1.在適當的時候釋放記憶體:有效地釋放無用的記憶體是常見的緩解記憶體壓力的手段,比如在場景切換的時候將前乙個場景的記憶體全部釋放掉,不過需要注意的是常見切換的時機,一般情況下要確保你切換到下一場景之前要將該場景初始化,有時強制釋放某些資源會導致正在執行的動畫失去引用而出現異常,這時可以通過呼叫ccactionmanager::sharedmanager->removeallactions();釋放動畫。

2.使用紋理貼圖集的方法,盡量拼接,使得的邊長保持在2的n次方,同時最好將有一點邏輯關係的打包在一張大圖里,從而能夠有效的節約記憶體。

3.使用ccspritebatchnode來減少相同的渲染操作。

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...