垃圾收集/链表

时间:2013-08-23 08:02:08

标签: garbage-collection go

垃圾收集器(理论上)会收集这样的结构吗?

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指向bb指向a。当我删除ab(最后两行)中的引用时,不再可以访问这两个节点。但每个节点仍然有一个参考。请问垃圾收集器会删除这些节点吗?

(显然不是在上面的代码中,而是在更长时间运行的程序中)。

垃圾收集器上是否有处理这些问题的文档?

2 个答案:

答案 0 :(得分:6)

程序中的垃圾收集器(GC)根目录是{a,b}。将所有这些内容设置为nil会使所有堆内容都有资格进行收集,因为现在所有现有节点(即使 引用)都不能从任何根到达。 / p>

同样的原则也保证了例如带有循环和/或自引用的结构一旦变得无法访问就会被收集。

答案 1 :(得分:3)

您描述的问题实际上是一个真正的问题,一个简单但很少使用的垃圾收集方案称为“引用计数”。基本上,正如您所暗示的那样,垃圾收集器(GC)计算给定对象存在多少引用,当该数字达到0时,它是GC'd。事实上,循环引用将阻止引用计数系统从GC结构化。

相反,许多现代GC所做的事情(包括Go;请参阅this post)是一个称为mark-and-sweep的过程。基本上,所有顶级引用(在某些函数范围内具有的指针)都标记为“可访问”,然后从这些引用引用的所有内容都标记为可访问,依此类推,直到所有可访问的对象都已标记为。然后,已知任何未标记的内容都无法访问,并且是GC'd。循环引用不是问题,因为如果它们没有从顶层引用,它们将不会被标记。