var a = [...]int{1,2,3,4,5,6}
s1 := a[2:4:5]
假设s1晚于a超出范围。 gc如何知道回收s1底层数组的内存?
考虑s1,spec的运行时表示
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
GC甚至不知道a的开头。
Go使用标记和扫描收集器作为它的当前实现。
根据算法,将有一个根对象,其余为树状结构,在多核机器的情况下,gc
与一个核心上的程序一起运行。
gc
将遍历树,当某些东西无法到达时,它会认为它是免费的。
Go对象还具有此post中所述的对象元数据。
摘录:
我们需要有关于对象的一些信息,因为我们没有标题。标记位保留在侧面并用于标记和分配。每个单词都有2位与之关联,以告诉您它是否是该单词中的标量或指针。它还编码了对象中是否有更多指针,因此我们可以尽早停止扫描对象。
原因是切片(切片头)是结构而不是指向结构的指针由russ cox在切片部分下的page中记录。
这是一段摘录:
Go最初表示一个切片作为指向结构的指针(切片头),但这样做意味着每个切片操作都分配了一个新的内存对象。即使使用快速分配器,也会为垃圾收集器创建大量不必要的工作,我们发现,与字符串的情况一样,程序避免了切片操作,有利于传递显式索引。删除间接和分配使得切片足够便宜,以避免在大多数情况下传递显式索引。
数组的大小(长度)是其类型的一部分。类型[1]int
和[2]int
是不同的。
要记住的一件事是go是面向价值的语言,而不是存储指针,它们存储直接值。
[3]int
,数组是go中的值,所以如果你传递一个数组,它会复制整个数组。 [3]int
这是一个值(一个整体)。
当你做a[1]
时,你正在访问部分价值。
SliceHeader
数据字段表示将此视为数组的基点,而不是a[0]
据我所知,我认为:
当一个人请求a[4]
时,
a[0]+(sizeof(type)*4)
计算。
现在,如果您通过切片s = a[2:4]
访问某些内容,并且如果有人请求s[1]
,那么请求的是,
a[2]+sizeof(type)*1