gpt4 book ai didi

dictionary - 在 Go 中,删除指针映射的条目会导致内存泄漏?

转载 作者:IT王子 更新时间:2023-10-29 01:19:44 27 4
gpt4 key购买 nike

这里是第一个计时器,

SliceTricks中的第一个NOTE暗示在剪切或删除指针 slice 中的元素时存在潜在的内存泄漏问题。

map 也是这样吗?例如:https://play.golang.org/p/67cN0JggWY

我们应该在从 map 中删除之前清零该条目吗?像这样:

m["foo"] = nil

如果我们只是清除 map 会怎样?

m = make(map[string]*myStruct)

垃圾收集器还会把它捡起来吗?

提前致谢

最佳答案

检查来源

虽然这在任何地方都没有记录,但检查来源:runtime/hashmap.gomapdelete() 函数:

558 func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
// ...
600 memclr(k, uintptr(t.keysize))
601 v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*uintptr(t.keysize) + i*uintptr(t.valuesize))
602 memclr(v, uintptr(t.valuesize))
// ...
618 }

如您所见,键(第 #600 行)和值(第 #602 行)的存储都被清除/归零。

这意味着如果任何键或值是一个指针,或者如果它们是包含指针的复杂类型的值,它们将被置零,因此指向的对象不再被映射的内部数据结构引用,所以有这里没有内存泄漏。

当不再引用一个完整的map值时,那么这个map的整个内存区域将被垃圾回收,key和key中包含的所有指针 map 也不再保留值;如果没有其他人引用指向的对象,它们将被正确地垃圾收集。

构造一个例子来证明这一点

我们还可以构造一个测试代码来证明这一点,而无需检查源代码:

type point struct {
X, Y int
}

var m = map[int]*point{}

func main() {
fillMap()
delete(m, 1)
runtime.GC()
time.Sleep(time.Second)
fmt.Println(m)
}

func fillMap() {
p := &point{1, 2}
runtime.SetFinalizer(p, func(p *point) {
fmt.Printf("Finalized: %p %+v\n", p, p)
})
m[1] = p
fmt.Printf("Put in map: %p %+v\n", p, p)
}

输出(在 Go Playground 上尝试):

Put in map: 0x1040a128 &{X:1 Y:2}
Finalized: 0x1040a128 &{X:1 Y:2}
map[]

这是做什么的?它创建一个 *Point 值(指向结构的指针),将其放入映射中,并注册一个函数,当该指针变得不可访问时(使用 runtime.SetFinalizer() )应该调用该函数, 然后删除包含此指针的条目。然后我们调用 runtime.GC() 来“强制”立即进行垃圾回收。我还在最后打印 map ,以确保整个 map 不会因为某些优化而被垃圾收集。

结果呢?我们看到已注册的函数被调用,这证明指针已作为 delete() 调用的结果从映射中删除,因为(因为我们没有其他引用)它符合垃圾条件收藏。

关于dictionary - 在 Go 中,删除指针映射的条目会导致内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39392467/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com