Memory management 卢阿-我可以吗;“清理”;一个不需要调用整个GC的弱表?

Memory management 卢阿-我可以吗;“清理”;一个不需要调用整个GC的弱表?,memory-management,garbage-collection,lua,Memory Management,Garbage Collection,Lua,我有一个表的键上有弱引用。我使用它来“注册”事件: 每隔一段时间,我执行所有“当前”事件;也就是说,我解析事件表并执行其回调 function launchEvents() for reference,callback in pairs(events) callback(reference) end end 此设置通常工作正常。一旦引用停止使用,它将被垃圾收集,其回调将从事件中消失 问题是-有时当引用已被消除,但垃圾收集器仍未运行时,执行launchEvents。在这种情况下,

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

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

function launchEvents()
  for reference,callback in pairs(events)
    callback(reference)
  end
end
此设置通常工作正常。一旦引用停止使用,它将被垃圾收集,其回调将从
事件中消失

问题是-有时当引用已被消除,但垃圾收集器仍未运行时,执行
launchEvents
。在这种情况下,我在
事件
中有一些“幻影引用”,并对基本上不存在的对象执行回调。例如,我创建了一个按钮,并将其关联为“单击”事件。然后我移除按钮(将其设置为nil)。在一秒钟左右的时间里,我仍然能够“点击它”,这是一种耻辱

我能找到的唯一修复方法是在launchEvents内手动运行GC:

function launchEvents()
  collectgarbage()
  for reference,callback in pairs(events)
    callback(reference)
  end
end
但这似乎有点过分了
launchEvents
每秒可能被调用多次。我调用整个垃圾收集周期只是为了清理一个表

有没有其他方法可以替代这种方法?我可以“垃圾收集”或“清理”一张桌子吗


附:我在Lua5.1中,顺便说一句,Lua的垃圾收集器不是那样工作的。您可以通过使用
lua\u GCSTEP
调用
lua\u gc
以增量方式运行它。但这并不能保证它会调查任何特定的物体

你的设计根本上有缺陷。如果您想收集一组事件,然后执行它们,然后收集一组新的事件,然后执行它们,那么您必须这样做。你需要明确地抛弃旧的事件;不要只是把它们放在一个弱表中,期望GC
nil
out引用


GC不象C和C++中的分配/解除分配。它是不规则和不可靠的。您不应该依赖它来实现实际的设计功能。

如果我没有弄错的话,您的程序是完全不同的(尽管相关),而且要大得多。使用自动内存管理,删除对象是不确定的,因此如果可以避免的话,不应该有语义影响。相反,您需要一种独立于垃圾收集的方法来“删除”(出于所有语义目的,例如显示和单击)对象。如果可能的话,我想将其限制为仅将引用设置为nil。在这种情况下,“事件”几乎被引用“压制”;真正的“次要”。我认为引用“太重要了,不能和事件混在一起”。你必须明确。唯一隐含的是GC可能会删除不再(强)引用的对象。事实上,完全不收集是有效的,除了可能耗尽内存之外,不应该破坏任何编写良好的程序。此外,我敢打赌代码中的许多地方对某些小部件有不止一个引用(可能是隐式的,例如临时引用或函数参数)。这实际上是一个很好的观点。回调本身可能仍然通过闭包隐式引用表。嗯……我想我必须继续我目前的设置,即使它感觉不那么自动。哦,好吧。谢谢
function launchEvents()
  collectgarbage()
  for reference,callback in pairs(events)
    callback(reference)
  end
end