【发布时间】:2011-09-17 00:55:07
【问题描述】:
我正在 Lua 中进行一个项目,我将在其中创建表并将它们存储在主表中,以便稍后删除。我会将这些表的引用传递给其他同级表。
master = {}
table.insert(master, {name = 'hello'})
table.insert(master, {name = 'world', pre = master[1]})
出现的问题是,当我希望从主表中删除引用时,该引用仍然保留在 master[2] 中。显然,我的第一个解决方案是让表格具有弱值。 (通过元表上的 .__mode,此处未显示)
只要我永远不会在这些表中存储单独引用的表,这行得通,而且会行得通。
table.insert(master, {name = 'goodbye', pre = master[2], some_table = {123}})
第三个元素 some_table 最终会被收集,因为这些表的值很弱,并且此表 (some_table) 不会在其他任何地方引用。这是不受欢迎的行为。我最新的解决方案涉及为主表中的表创建“弱引用对象”。一个简单的实现如下:
function WeakRef(t)
r = {__mode = 'v', __index = t, __newindex = t}
setmetatable(r, r)
return r
end
这些弱引用对象的行为类似于boost::weak_ptrs 并实现了我的目标,但我不确定它们是否是我问题的最佳解决方案。
有没有更好的方法;更优雅的解决方案? 我的设计是否需要这个主表,可能有缺陷?
【问题讨论】:
-
"出现的问题是,当我希望从主表中删除引用时,引用仍然保留在 master[2] 中。"我很好奇为什么这是一个问题。是否需要通知其他代码真的 从主表中删除对象?因为 GC 不保证收集这些东西的时间范围。在 Lua 中需要如此严格的内存控制的设计到底是什么?
-
他们本身不一定需要立即通知。预期设计是在模拟中指示物理对象的主阵列,当不再需要该对象时,可以将其移除。它类似于在一个数组中拥有一组强指针,然后围绕指向对象的弱指针展开。我的问题是我给对象提供了对其他对象的引用,如果我希望立即从模拟中删除一个对象,这可以阻止集合。这有意义吗?
-
我明白你在做什么。我不确定为什么你这样做。既然弱引用不能保证立即消失,那么它们是否消失又有什么关系呢?那是我不明白的部分:为什么其他引用需要弱?弱引用不会防止意外使用死对象,因为 GC 可能还没有收集到它。它们变弱的唯一原因是为了防止循环依赖(Lua 没有问题)或者更有效地管理内存。您是否分配了足够的数据以致内存管理成为问题?
-
我没有分配足够的数据,这在这一点上是个问题。我担心的是更少的记忆和更多的有效性。就像如果我想说“这个对象已经死了”,那么我希望它被删除并且对它的任何引用都为零。如果这个物体在下一次扫荡之前一直悬在某处未被收集,对我来说是可以的;一旦我宣布它“死亡”,我就不想再引用它了。
标签: garbage-collection lua weak-references