lua - 我可以“清理”弱表而无需调用整个GC吗?

时间:2012-02-03 15:44:17

标签: memory-management garbage-collection lua

我有一个表,其键上有弱引用。我用它来“注册”事件:

local events = setmetatable({}, {__mode="k"})

function registerEvent(reference, callback)
  events[reference] = callback
end

每隔一段时间我就会执行所有“当前”事件;也就是说,我解析events表并执行其回调。

function launchEvents()
  for reference,callback in pairs(events)
    callback(reference)
  end
end

此设置通常可以正常工作。一旦引用停止使用,它就会被垃圾收集,其回调将从events消失。

问题是 - 有时launchEvents在删除引用时执行,但垃圾收集器仍然没有运行。在这种情况下,我在events中有一些“幻像引用”,并且对基本上不再存在的对象执行回调。例如,我创建一个按钮并将其与“click”事件相关联。然后我删除按钮(将其设置为零)。大约一秒左右,我仍然可以“点击它”,这是一种耻辱。

我能找到的唯一解决方法是在launchEvents中手动运行GC:

function launchEvents()
  collectgarbage()
  for reference,callback in pairs(events)
    callback(reference)
  end
end

但这似乎有点矫枉过正。每秒可以多次调用launchEvents。我正在调用完整的垃圾收集周期来清理一个表。

这种方法有替代方案吗?我可以“垃圾收集”或“清理”一个弱桌吗?

PS:顺便说一下,我在Lua 5.1中。

1 个答案:

答案 0 :(得分:2)

Lua的垃圾收集器不起作用。您可以使用lua_gc调用LUA_GCSTEP以递增方式运行它。但这并不能保证会调查任何特定的对象。

您的设计存在根本缺陷。如果你想收集一堆事件,然后执行它们,然后收集一堆新的事件,然后执行它们,那么你必须这样做。你需要明确扔掉旧事件;不要只是将它们放在弱表中,并期望GC将nil输出参考。

GC与C和C ++中的分配/释放不同。这是不规则和不可靠的。您不应该依赖它来实现实际的设计功能。