【问题标题】:how a pointer to a struct member keeps the struct alive in Go指向结构成员的指针如何使结构在 Go 中保持活动状态
【发布时间】:2022-07-20 02:14:53
【问题描述】:

给定以下 golang 代码:

type Pointer struct { x, y int }

func foo(p *Pointer) *int {
    return &p.y
}

CompilerExplorer 表明return &p.y 编译为

TESTB   AL, (AX)
ADDQ    $8, AX
RET

这很容易理解。 TESTB 是一个空检查,然后ADDQ 通过将Pointer::y 的偏移量添加到p 来生成指向p.y 的指针。

我不明白的是,给定一个指向p.y 的指针,垃圾收集器怎么知道它不仅仅是一个任意的*int,而是一个指向Pointer::y 的指针,所以p 必须保持活动状态只要指向p.y 的指针还存在?

【问题讨论】:

  • 垃圾收集器知道堆中的所有对象及其大小。在这个例子中,如果p 在堆中,那么垃圾收集器就会知道一个指针指向一个结构所拥有的区域,从而使结构保持活动状态。
  • @BurakSerdar 有什么样的数据结构和算法? GC要快,所以时间复杂度应该是O(1)吧?
  • 我不确定 GC 的内部结构,但我认为不是 O(1)。不过,如果您在内存中有一个已排序的对象数组,您可以使用二分查找来查找指针是否落入某个范围内。
  • gc(编译器)的GC(Garbage Collector)是一种mark-and-sweep。你可以在这里找到更多信息:tip.golang.org/doc/gc-guide

标签: go garbage-collection


【解决方案1】:

看完source code我找到了答案。

  1. 使用基于竞技场/跨度的分配。
  2. 竞技场和跨度与页面对齐,因此计算指针指向的竞技场很简单。
  3. 有一个全局向量存储所有竞技场和跨度的元数据。
  4. 每个跨度都有一个固定的“元素大小”。同一跨度中的所有对象都具有相同的大小。
  5. 给定指针p、span 的基地址b 和span 的元素大小s,我们知道指针指向span 中的第n 个元素,其中n = (p - b) / s
  6. 所以spanb + s * n中第n个对象的地址,需要标记为活动的。

【讨论】:

    猜你喜欢
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-09
    • 1970-01-01
    • 2017-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多