问题描述
我正在学习 Go,作为练习,我想实现一个链表.作为参考,我查看了官方 Go 代码(
- 我们创建一个指向Node2的外部指针
- 我们从列表中删除节点 2-4
- 此时您只会期望节点 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.
- We create an external pointer pointing to Node2
- We remove nodes 2-4 from the list
- 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屋!