1. 程式人生 > >關於lua的弱引用表和指向c++的記憶體

關於lua的弱引用表和指向c++的記憶體

公司客戶端程式碼有個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型別,無法被正確釋放。至於原因,還在調查。