golang 的 GC 如何处理 unsafe.Pointer?
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?
最近在 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.Pointer
和 unsafe.Pointer
间的赋值一定是安全的,但是间接的赋值(比如同过 uintptr)可能是非法的,因为 uintptr 不被认为持有了对象。
go 会忽视所有非 go 分配的对象(比如 C.malloc),所以如果在 C 中有一个指针指向的地址包含了 go 的对象,那么必须保证这个指针在 go 中也被一个对象存储下来。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK