關於lua的弱引用表和指向c++的記憶體
阿新 • • 發佈:2018-11-09
公司客戶端程式碼有個viewMgr類,用來管理各個彈框的層級顯示,但是由於每次場景切換都需要手動先close一次。秉持著用更少的程式碼實現功能,同時主要是怕我的隊友在使用時忘記close時導致的BUG,因此打算研究研究看看有沒有辦法自動釋放記憶體。
核心程式碼如下:
function ViewMgr:openView(viewName, data) if nil == self._openedView[viewName] then if nil == self._registView[viewName] then cclog(viewName .. " has not regist in viewMgr!!!!") end self._openedView[viewName] = self._registView[viewName].new(data) end return self._openedView[viewName] end
由此可見,只要這個view在之前open過一次後,下次就直接從self._openedView中讀取。但是在切換場景是,系統會自動將view釋放掉,因此這裡還保留有view的指標,就導致下次再open會出錯。
之前在研究lua記憶體洩漏時,知道了lua還有個弱引用功能,參考下面程式碼:
local tb1 = {} --setmetatable(tb1, {__mode = "k"}); tb1[1] = {"55"} tb1[2] = {2,3,4}; tb1[3] = {5,6,7}; tb1[4] = {5,6,7}; local openedView={} setmetatable(openedView, {__mode = "v"}); openedView['aaa'] = tb1; print("getn: " .. table.getn(tb1)); print(openedView['aaa'][2][2]); tb1=nil --立刻釋放記憶體 collectgarbage() print(openedView['aaa'][2][2]);
可知,在lua中,通過setmetatable設定__mode為'k','v','kv'的一種或多種,就可以設定table中指定項是否為弱引用,如果是弱引用,當k,v被釋放時,也會導致table對應的專案釋放掉。
setmetatable(t, {__mode = “k”});
setmetatable(t, {__mode = “v”});
setmetatable(t, {__mode = “kv”});
由此可見lua的弱引用是解決我問題的最佳方案,只要切場景時被釋放了,下次openview就會重新建立。
可惜現實不然,經測試,這個弱引用只對lua 的型別有用,每次new出來的view都是一個userdata型別,無法被正確釋放。至於原因,還在調查。