为什么要将userdata对象添加到这个Lua 5.1\u gc解决方案中的表中?
我正在寻找在Lua5.1中向我的表(对象)添加垃圾收集的解决方案。我发现可以使用为什么要将userdata对象添加到这个Lua 5.1\u gc解决方案中的表中?,lua,garbage-collection,Lua,Garbage Collection,我正在寻找在Lua5.1中向我的表(对象)添加垃圾收集的解决方案。我发现可以使用newproxy()和\uu gc解决这个问题: 我不明白的是作者使用了将userdata作为字段插入表中 通过此包装器设置元表的所有对象都会被特殊键\uuu gc\u proxy“污染”(可以是任何字符串,用户可通过\uu gc\u proxy global定义)。如果遍历表的字段(next(),pairs()…),则必须对其进行特殊处理 及 在使用建议的解决方案时,有一件事需要关注——如果您将通过pairs(
newproxy()
和\uu gc
解决这个问题:
我不明白的是作者使用了将userdata作为字段插入表中
通过此包装器设置元表的所有对象都会被特殊键\uuu gc\u proxy“污染”(可以是任何字符串,用户可通过\uu gc\u proxy global定义)。如果遍历表的字段(next(),pairs()…),则必须对其进行特殊处理
及
在使用建议的解决方案时,有一件事需要关注——如果您将通过pairs()遍历表,您将得到一个加法键。通过使用具有适当元方法的代理对象代替原始表,可以避免这种情况
下面是堆栈溢出线程的复制/粘贴示例:
function setmt__gc(t, mt)
local prox = newproxy(true)
getmetatable(prox).__gc = function() mt.__gc(t) end
t[prox] = true
return setmetatable(t, mt)
end
iscollected = false
function gctest(self)
iscollected = true
print("cleaning up:", self)
end
test = setmt__gc({}, {__gc = gctest})
collectgarbage()
assert(not iscollected)
for k, v in pairs(test) do
print(tostring(k) .. " " .. tostring(v))
end
输出为:
userdata: 0003BEB0 true
cleaning up: table: 00039D58
但此清理是从脚本结尾开始的,而不是在调用collectgarbage()
时进行的
这可以通过一个以循环结束的稍加修改的版本来证明。输出应为“清理”:
相反,通过删除有问题的t[prox]=true
,集合可以按预期工作:
function setmt__gc(t, mt)
local prox = newproxy(true)
getmetatable(prox).__gc = function() mt.__gc(t) end
t[prox] = true
return setmetatable(t, mt)
end
function gctest(self)
print("cleaning up")
io.flush()
end
test = setmt__gc({}, {__gc = gctest})
collectgarbage()
while (true) do
end
输出:
cleaning up
但此清理是从脚本结束时开始的,而不是在调用collectgarbage()时进行的。
-发生这种情况的原因是全局变量test
锚定表,因此在程序退出之前无法对表进行垃圾收集,但此清理是从脚本结束时开始的,而不是在调用collectgarbage()时进行的
-发生这种情况的原因是全局变量test
锚定表,因此在程序退出之前无法对表进行垃圾收集
cleaning up