3

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

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(最后两行)中的引用时,这两个节点不再可访问。但是每个节点仍然有一个引用。go 垃圾收集器会删除这些节点吗?

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

是否有关于处理这些问题的垃圾收集器的任何文档?

4

2 回答 2

6

程序中的垃圾收集器 (GC) 根集是 {a, b}。将它们全部设置为 nil 使所有堆内容都符合收集条件,因为现在所有现有节点,即使它们引用,也无法从任何根访问。

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

于 2013-08-23T08:09:05.677 回答
4

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

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

于 2013-08-23T15:30:20.297 回答