4

golang 的 GC 如何处理 unsafe.Pointer?

 3 years ago
source link: https://www.purewhite.io/2019/04/01/golang-gc-consider-unsafe/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

golang 的 GC 如何处理 unsafe.Pointer?

发表于 2019-04-01 更新于 2019-10-30 分类于 go 阅读次数:1276 Disqus:2 Comments
本文字数: 744 阅读时长 ≈ 1 分钟

最近在 golang 的邮件列表中看到了一篇关于 GC 如何处理 unsafe.Pointer 的讨论,觉得应当记录一下。


问题 1:如果一个对象只被 unsafe.Pointer 所指向,那么这个对象会被回收么?

回答 1:不会。如果 unsafe.Pointer 指向了一个对象,那么 go 的 GC 会知道有这个对象,并且不会释放这个对象的内存。

但是注意,有一个例外:如果这个对象的内存是在 go 外被分配的(比如 C.malloc),那么以上的规则不生效。


问题 2:如果这个对象内部也有一些指针,那么 GC 会如何处理这些指针?

回答 2:如果这个对象是在 go 内部分配的,那么 GC 也会遍历这些指针(也就是不会被释放)。


问题 3:如果在以上两个问题中,对象都不会被释放,那么 GC 是怎么处理的?unsafe.Pointer 会存对象的类型信息么?

回答 3:不会存类型信息,但是如果对象是在 go 中申请的,那么在对应的内存中是会存有类型信息的;如果没有类型信息,那么 GC 会采用非常保守的策略:遍历整个对象,只要其中有 8bit 的值是合法的内存地址(在栈范围内,或者在堆上),就认为是指针,不会进行回收。


问题 4:有没有一种情况 unsafe.Pointer 会变成非法的(野指针)?

回答 4:在 go 中,只要 unsafe.Pointer 有一刻是合法的,并且它的值没有修改,那么 go 会保证它在整个程序的生命周期中都是合法的。在 unsafe.Pointerunsafe.Pointer 间的赋值一定是安全的,但是间接的赋值(比如同过 uintptr)可能是非法的,因为 uintptr 不被认为持有了对象。


go 会忽视所有非 go 分配的对象(比如 C.malloc),所以如果在 C 中有一个指针指向的地址包含了 go 的对象,那么必须保证这个指针在 go 中也被一个对象存储下来。

原文


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK