記憶體管理中經常遇到的問題:記憶體洩露,記憶體溢位。
在cocos2dx中用的是引用計數和自動釋放池的技術,由於熟悉objective-c語言,所以對這兩個概念不會很陌生。
一、引用計數
引用計數是自動記憶體管理的基礎:在物件裡增加乙個引用計數,當外部引用增加時,計數器加1,當外部引用消失時,計數器減1 。
看一下ccobject原始碼:
class
cc_dll ccobject
:public
cccopying;
friend
class
ccautoreleasepool;};
其中m_ureference就是用於計數的整形變數,在這裡就記錄了當前物件的引用計數。
跟objective-c一樣,retain是計數器加1, release是計數器減1, 計數器為0的時候會自動清除物件。
加1 減1 操作如下:
void
ccobject
::release
(void)}
void
ccobject
::retain
(void)
上面的引用計數只是自動管理的方式,通過這種方式cocos2dx引擎會曉得何時釋放物件。
在這裡之前需要保證引用計數的準確性,建議:
1、開始對應著結束,建立(new,copy)了物件就一定要釋放(release)。
2、引用了就要釋放, 也就是說 呼叫了retain後就要呼叫release。
3、引數傳遞需要更替引用。 當物件指標作為引數傳遞的時候,在函式內需要引用物件,這時候就需要釋放掉舊的物件,然後增加新的物件:
void a(b *b)
來解釋一下上面函式為何先增加 再減少引用計數,然後賦值:
1、retain(b)是因為 b指向乙個b 物件,retain一次是為了保證b不被銷毀。保留一次值。
2、release(m_b) 是因為m_b是乙個屬性,在這裡實際上是要釋放掉上次賦給他的值。
3、這裡是m_b和b指向相同的物件,擁有相同的引用計數。 呼叫完畢後,他們的引用計數是1。
二、自動釋放池
ccpoolmanager 這個類是自動釋放吃計數的精髓。
我們可以將物件放在自動釋放吃中,在引擎每次繪製週期結束的時候,就會自動釋放池中的物件。
具體的使用:
ccobject *obj = new ccobject;
obj->autorelease(); 將物件加入自動釋放池中。
1、原理
如上面**,建立乙個obj物件,通過autorelease將他加入到自動釋放池中, 使用函式設定自動釋放功能時,記憶體管理類ccpoolmanager就會把這個當前物件加入到管理池中,等到特定的時候,記憶體管理著就會遍歷其所管理的每乙個物件,逐個呼叫物件的釋放函式進行釋放。
ccobject
*ccobject
::autorelease
(void)
再看addobject函式:
void
ccpoolmanager
::addobject
(ccobject
*pobject)
ccautoreleasepool
*ccpoolmanager
::getcurreleasepool()
ccassert
(m_pcurreleasepool
,"current auto release pool should not be null");
return
m_pcurreleasepool;
}
void
ccautoreleasepool
::addobject
(ccobject
*pobject)
可以看到,
ccarray
*m_pmanagedobjectarray
; 這是乙個陣列;
在上面函式的最後一句呼叫了release, 這是因為 在前面addobject新增到陣列的時候,增加了一次物件的引用計數。
下面看看物件自動釋放的過程:
void
ccpoolmanager
::push()
void
ccpoolmanager
::pop()
intncount
=m_preleasepoolstack
->
count
(); //獲取當前釋放池中物件的數目
m_pcurreleasepool
->
clear
(); //釋放自動釋放池中的內容
if(ncount
>
1) //自動釋放吃多於乙個 下面就減少乙個
m_pcurreleasepool=(
ccautoreleasepool
*)m_preleasepoolstack
->
objectatindex
(ncount-2
); }
/*m_pcurreleasepool = null;*/
}
**中, m_preleasepoolstack
是儲存多個釋放吃的地方, 要注意第乙個自動釋放池實在ccdirector建構函式中建立的。
在ccpoolmanager類中,你會看到他可以儲存多個自動釋放池, 自動釋放池中儲存的是物件。 所以自動釋放吃的建立和釋放是由manager來負責的。
來看一下是怎麼釋放的:
void
ccautoreleasepool
::clear()
m_pmanagedobjectarray
->
removeallobjects
(); //釋放池中的所有物件}}
在這裡,在釋放之前,pobject的標記autorelease count會減1 。 這樣是為了避免釋放物件後產生錯誤。 所以,自動釋放池技術也不是永遠都可以依賴的,他也是依賴引用計數,只要引用存在,記憶體就不能**。
cocos2dx 引擎通過管理模式來實現自動釋放池的技術。 在這裡很多地方都使用了管理模式。 管理模式+緩衝區 可以很好地管理記憶體資源。
三、管理模式
在cocos2dx中,不僅僅只有前面使用的ccpoolmanager, 還有動作管理者,指令碼管理者等等。
1、在引擎當中,只會存在乙個管理者,如:自動釋放池管理者,動作管理者等等。 為了保證管理者的唯一性,管理者模式的物件都會是單例。 通過share字首函式獲得單例,purge字首函式釋放單例。
2、管理模式可以管理物件,他會負責所管理物件的建立和銷毀。
3、管理模式的優點是為一組相關的物件提供乙個統一的全域性訪問點,同時可以提供一些簡潔的介面來獲取和操作這些物件。 用他來快取遊戲中的常有資源,可以提高遊戲執行時的效能。
看看緩衝區:
遊戲中有的資源不會被常用,只出現幾次,但是有的資源經常會出現,這樣我們就可以將他們放在緩衝區了。
這樣存在記憶體不夠的情況,這樣在記憶體占用過多的時候可以來釋放相應的緩衝區。
在緩衝區的內部也使用了引用計數的方式來管理物件資源,可以通過retain和release來進行控制。
我們也可以通過緩衝區進行預載入的操作。 但是要注意清理。
cocos2d x 記憶體管理
呼叫了autorelease的物件,將會在自動 池釋放的時候被釋放一次。因為這個操作發生在 mainloop drawscene 後,這時候遊戲中所有的邏輯已經執行完畢,正是釋放無效資源的最佳時機。所以乙個物件被create後,將被放進pool中,其ref 數為1,當遊戲整個邏輯跑完,如果沒有增加r...
cocos2dx 記憶體管理
我們知道,cocos2dx中使用了引用計數的方式去管理記憶體,不需要我們手動delete的去釋放記憶體。那麼cocos2dx中是怎麼實現引用計數的記憶體管理方式的呢?cocos2dx中的記憶體管理用到了兩個工具 引用計數器 ref 自動 池 autoreleasepool 引用計數器 ref ref...
Cocos2d x 記憶體管理
一 記憶體管理機制 cocos2d x是一套基於c 的引擎,c 的記憶體機制,如果採用new關鍵字宣告乙個物件而沒有手動delete掉,那麼申請的記憶體就不會被 進而造成記憶體洩露。cocos2d x是採用引用計數的方式管理記憶體,基本的原則就是當構造乙個物件時,引用計數為1,每次進行retain操...