cocos2dx 學習( )記憶體管理機制

2021-06-29 08:47:11 字數 2591 閱讀 5912

**:

一、題記

關於cocos2dx 的記憶體管理機制,想必大家都能清楚說出是通過引用計數(reference count)和自動釋放池(autoreleasepool)。但是不知大家是否知道其中具體的執行的細節呢?反正在寫這篇blog之前我是一知半解的,而且在粗略的看了下 poolmanager 的原始碼時我還開始懷疑過這個機制的可靠性,於是我還專門找了測記憶體洩漏的工具 vs2010使用vld檢測記憶體洩露,一測發現專案還真存在記憶體洩漏的問題。可是後來發現原來是自己用的別人的敏感字過濾開源庫(存在問題。經我改造後( 的版本修復此問題,並調整了api的結果。可是修復了我自己的**的記憶體洩漏的問題後,發現 cocos2dx 真的有記憶體洩漏(哈哈終於抓到尾巴了內心竊喜)。可是發現原來只是cocos2dx 乙個單例模式的物件忘記了釋放而已(這裡我想吐槽cocos2dx 單例模式的實現,這裡可以參考我之前寫的一篇關於單例模式實現方式的博文並不是我想得poolmanager 導致的。終於發現原來cocos2dx 的記憶體管理模式其實應該 是  引用計數(reference count)和自動釋放池(autoreleasepool)和 內建ccvector和其它cocos2dx內建容器類輔助實現的。下面來自己分析一下。

1、首先要說說我為什麼懷疑它的可靠性。

因為我發現cocos2dx 的 autoreleasepool 其實是通過 poolmanager  在每一幀呼叫一次clear

[cpp]view plain

copy

void

displaylinkdirector::mainloop()  

else

if(! _invalid)  

}  [cpp]view plain

copy

void

autoreleasepool::clear()  

_managedobjectarray.clear();  

#if defined(cocos2d_debug) && (cocos2d_debug > 0)

_isclearing = false

;  #endif

}  

仔細看了一下clear的實現後發現乙個漏洞,那就是 它在將 _managedobjectarray 中的obj relase 之後就將 _managedobjectarray clear 了,那那些 release之後 引用計數還是大於0的誰來管理呢?我檢視了 node, ref 的實現中,都沒有找到對這些obj 管理,原先使用過程中我們知道 addchild 後就不怕被 poolmanager 給釋放了。但是我在addchild中也沒看到 retain 在 removefromparent 也沒看到 release 的操作,於是我就產生了疑問。

2、如何快速找到問題的關鍵的。

還好我在上一家公司學會了vs的各種除錯技巧(用資料斷點的方式檢視 ref 的引用計數變數的變化),讓我一下子就找到了問題的所在。原來這個管理工作隱藏在了 內建容器 vector 中了。

[cpp]view plain

copy

void

pushback(t object)    

[cpp]view plain

copy

void

popback()    

3、隱藏的乙個危險,不知道大家有沒有注意到 ref 裡面乙個debug才會執行的**

[cpp]view plain

copy

void

ref::release()  

#endif

#if cc_use_mem_leak_detection

untrackref(this

);  

#endif

delete

this

;  }  

}  

他在delete之前先判斷了下這個obj是否還在管理池中。細想一下這裡真的存在乙個危險的問題,那就是如果你把乙個obj新增到池中了。然後你池中儲存了這個obj的指標,但是如果你在新增到池的這一幀中又release了1次這個obj,那麼會導致這個記憶體池中存了乙個野指標,那麼接下來等著你的就是程式掛掉了。

4、總結:

cocos2dx 中記憶體管理是基於 

引用計數

(reference count)和自動釋放池(autoreleasepool)和 內建ccvector和其它cocos2dx內建容器類輔助實現的,而且要

注意的是它是按幀管理的。也就是它只負責你在前一幀中那些沒有被利用到的obj幫你自動處理了

。cocos2dx 中 class的 static create 介面都將產生 autorelase 的obj,如果autorelease的obj在產生後沒有找到管理的宿主(執行retain),那麼就會在下一幀被poolmanager 給clear掉。

關於cocos2dx 中記憶體池中這個隱含的危險。我們只要注意不要在同一幀中將乙個obj加入池中又將其release就行了。

另外cocos2dx 中存在大量的單例物件,官方可能存在忘記釋放這些單例物件的情況,這時候我們可以通過 vld 快速的定位到,自己進行對應的修改是指能夠被正確釋放掉。

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