2013-08-23 60 views
2

垃圾收集器(理论上)是否会收集这样的结构?垃圾收集/链接列表

package main 

type node struct { 
    next *node 
    prev *node 
} 

func (a *node) append(b *node) { 
    a.next = b 
    b.prev = a 
} 

func main() { 
    a := new(node) 
    b := new(node) 
    a.append(b) 
    b = nil 
    a = nil 
} 

这应该是一个链表。 a积分b,b积分返回a。当我删除ab(最后两行)中的引用时,两个节点不能再访问。但是每个节点仍然有一个参考。去垃圾收集器会删除这些节点吗?

(显然不是在上面的代码中,而是在一个较长的运行程序中)。

有没有处理这些问题的垃圾回收器的任何文档?

回答

4

程序中垃圾回收器(GC)根的集合是{a,b}。将它们全部设置为零使得所有堆内容有资格收集,因为现在所有现有节点(即使它们参考的)都不是来自任何根的

同样的原则也保证了例如一旦它们变得不可达时就收集具有循环和/或自引用的结构。

+0

谢谢!我会尽量多了解一些GC,特别是Go的GC。你偶然知道Go的垃圾收集器的任何文档吗? – topskip

+0

@topskip:不幸的是我不知道这样的文档。它曾经是一个保守的GC,目前主要是一个精确的GC,剩下的地方很少(我认为调用记录[堆栈帧]还不精确)。 – zzzz

2

您所描述的担忧实际上是一个真正的问题,即使用一种简单但很少使用的垃圾回收机制,称为“引用计数”。基本上,就像你暗示的那样,垃圾回收器(GC)计算给定对象有多少引用,当该数字达到0时,它就是GC'd。而且,实际上,循环引用将阻止引用计数系统对该结构进行GC处理。

取而代之的是许多现代GC所做的(包括Go;参见this post)是一个被称为mark-and-sweep的过程。实质上,所有顶级引用(您在某个函数范围内指向的指针)都会标记为“可达”,然后将从这些引用引用的所有内容标记为可访问,依此类推,直到所有可访问的对象都已标记为止。然后,任何未被标记的东西都被认为是不可达的,并且是GC'd。循环引用不是问题,因为如果它们没有从顶层引用,它们将不会被标记。

+0

感谢您的好解释(+链接)! – topskip

+0

是的,没问题! – joshlf