cocos2dx 記憶體管理

2021-06-23 06:54:23 字數 3671 閱讀 1414

記憶體管理中經常遇到的問題:記憶體洩露,記憶體溢位。

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