关于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类型,无法被正确释放。至于原因,还在调查。

猜你喜欢

转载自blog.csdn.net/ch_majia/article/details/82801156
今日推荐