【发布时间】:2017-08-12 06:17:53
【问题描述】:
在 Go 中获取地址并返回指向函数内部局部变量的指针会导致编译器将其分配在堆上而不是堆栈上,因此返回的指针仍然有效。
现在如果我获取并返回结构成员或嵌入式结构的地址会发生什么?
type A struct {
a,b,c int
}
type B struct {
A
d,e,f int
}
func (b *B) get1() *A {
return &b.A
}
func (b *B) get2() *A {
localB := B{}
return &localB.A
}
编译器会在堆上分配嵌入式结构 A 并将 B 的成员保留在堆栈上吗?
即使 localB.A 引用仍在使用中,垃圾收集器也会收集 localB 吗?
如果通过反射访问,编译器如何确定何时将嵌入式结构保留在堆栈或堆上?
【问题讨论】:
-
Go 在这里很安全。你只是不能产生悬空指针,你做什么都没关系(如果你远离包不安全)。编译器在这里玩得很安全:如果它不能证明堆栈上的分配是安全的,它将在堆上分配。没什么可担心的;继续前进。
-
@Volker 我不担心悬空指针,但我担心封闭结构不会很快被垃圾收集。
-
首先:类型 A 是空的,因此在您的示例中没有要收集的内容。假设 A 在现实生活中不是空的,那么如果 localB.A 正在使用,GC 如何收集 localB?您是否假设 GC 已损坏?
-
假设A不为空并且B除了A之外还有其他成员,那么是的,就像答案之一的逃逸分析链接中提到的那样,Go逃逸分析并不完美,因此垃圾收集不是也很完美。所以我们可以在一定程度上说它是“破碎的”或更好的词——不完美。现在,如果我的结构 B 很大而 A 很小,那么这个缺陷对于了解我是否处理数百万个 B 很重要。我可以想象,即使 A 无法收集,理想的 GC 也应该有可能对 B 的部分进行垃圾收集。
标签: go pointers struct heap-memory