【发布时间】:2012-02-04 01:38:38
【问题描述】:
我有一张表,其键上的引用很弱。我用它来“注册”事件:
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 中有一些“幻像引用”,并且为基本上不再存在的对象执行了回调。例如,我创建了一个按钮并将其与“单击”事件相关联。然后我删除按钮(将其设置为零)。一秒钟左右,我仍然能够“点击它”,这很遗憾。
我能找到的唯一解决方法是在 launchEvents 中手动运行 GC:
function launchEvents()
collectgarbage()
for reference,callback in pairs(events)
callback(reference)
end
end
但这似乎有点矫枉过正。 launchEvents 每秒可能会被调用多次。我调用完整的垃圾回收周期只是为了清理一张表。
这种方法有替代方法吗?我可以只“收集”或“清理”一张薄弱的桌子吗?
PS:顺便说一句,我在 Lua 5.1 中
【问题讨论】:
-
如果我对您的理解正确,您的程序完全不同(尽管相关)并且更大。使用自动内存管理,对象的删除是不确定的,因此不应该有语义影响,如果可以避免的话。相反,您需要一种方法来“删除”(出于所有语义目的 - 例如显示和可点击)独立于垃圾收集的对象。
-
我不想明确“删除”。如果可能的话,我想将其限制为简单地设置对 nil 的引用。在这种情况下,“事件”几乎“屈服于”引用。真的“次要”。我认为引用“太重要了,不能与事件混在一起”。
-
你必须是明确的。唯一隐含的是 GC 可能 删除不再(强烈)引用的对象。事实上,根本不收集是有效的,并且不应该破坏任何编写良好的程序,除非它们可能会耗尽内存。此外,我敢打赌,您的代码中的许多地方都不止一次引用了某个小部件(可能是隐式引用,例如临时引用或功能参数)。
-
这实际上是一个非常好的观点。回调本身可能仍然隐式引用表 - 通过闭包。嗯..
标签: memory-management garbage-collection lua