问题描述

我正在学习 Go,作为练习,我想实现一个链表.作为参考,我查看了官方 Go 代码(

  1. 我们创建一个指向Node2的外部指针
  2. 我们从列表中删除节点 2-4
  3. 此时您只会期望节点 1,2 &5 个活着,其余的被 GC 控制.但是,由于 Node2 仍然指向 Node3 &等,整个链仍未收集.

您的假设是正确的.如果有一组相互指向的指针,但没有指向该组任何成员的引用/指针,则该组将被垃圾收集器检测为不可达并被正确释放.

list.ElementElement.nextElement.prev
nil

看这个例子:

var e2 *list.Element功能主(){列表测试()fmt.Println(e2.Value)//此时我们期望列表中的所有内容//垃圾随时收集,我们只有 e2 的引用.//如果 e2.prev 和 e2.next 不会被设置为 nil,//无法释放 e1 和 e3!}功能列表测试(){l := list.New()e1 := l.PushBack(1)e2 = l.PushBack(2)e3 := l.PushBack(3)//列表现在是 [1, 2, 3]fmt.Println(e1.Value, e2.Value, e3.Value)l.移除(e2)//现在列表是 [1, 3],它不包含 e2}
listTest()e2e2listTest() 之外无法访问列表>listTest()e2e2
e2prevnextnilList.Remove()nile1e3

I'm learning Go, and as an exercise I wanted to implement a linked list. For reference I looked at the official Go code (https://golang.org/src/container/list/list.go) . One thing that stuck with me are these lines:

   108  // remove removes e from its list, decrements l.len, and returns e.
   109  func (l *List) remove(e *Element) *Element {
   110      e.prev.next = e.next
   111      e.next.prev = e.prev
   112      e.next = nil // avoid memory leaks
   113      e.prev = nil // avoid memory leaks
   114      e.list = nil
   115      l.len--
   116      return e
   117  } 

I am curious as to how does setting pointers to nil in this case prevent memory leaks? If possible I would like to construct a program which has this flaw and see it while profiling with pprof (I would use a modified verion of the list.go without this nil pointer setting).

For clarity of answer: If one of the nodes has an external pointer to it, then all of the adjacent removed nodes will have an active reference through that pointer and won't be removed.

  1. We create an external pointer pointing to Node2
  2. We remove nodes 2-4 from the list
  3. You would expect at this point only for the Node 1,2 & 5 to be alive and the rest to be GC-ed. However, due to Node2 still pointing to Node3 & etc., the entire chain remains uncollected.

Your assumptions are correct. If there is a group of pointers pointing to each other, but there is no reference / pointer to any member of this group, the group will be detected as unreachable by the garbage collector and will be freed properly.

list.ElementElement.nextElement.prev
nil

See this example:

var e2 *list.Element

func main() {
    listTest()
    fmt.Println(e2.Value)
    // At this point we expect everything from the list to be
    // garbage collected at any time, we only have reference to e2.
    // If e2.prev and e2.next would not be set to nil,
    // e1 and e3 could not be freed!
}

func listTest() {
    l := list.New()
    e1 := l.PushBack(1)
    e2 = l.PushBack(2)
    e3 := l.PushBack(3)
    // List is now [1, 2, 3]
    fmt.Println(e1.Value, e2.Value, e3.Value)
    l.Remove(e2)
    // Now list is [1, 3], it does not contain e2
}
listTest()e2e2listTest()listTest()e2e2
prevnexte2nilList.Remove()nile1e3

这篇关于将指针设置为 nil 以防止 Golang 中的内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!