这段代码安全吗? b 在 if 块结束时进行描述,但 a 仍然指向 b 的内存地址。在这个简单的例子中它似乎工作(它打印正确的值),但它在语言规范中,这总是有效吗?
使用-m进行编译以检查编译器优化,它说 b 不会转义到堆。
游乐场:http://play.golang.org/p/ZzYkMg6FqB
package main
import "fmt"
func main() {
a := new(int)
*a = 10
if *a > 0 {
b := 5
a = &b
}
fmt.Println(*a)
}
答案 0 :(得分:2)
Go中没有悬空指针。
b
是否超出范围无关紧要; a
现在拥有该地址,并将由GC进行扫描。
答案 1 :(得分:2)
代码是安全的。 Go中的任何赋值都具有复制语义,所以
a = &b
相当于
c = &b
a = c
指派您参考,您可以有效地获取此参考的副本
所以这肯定也会起作用
b := 5
c := &b
a = c
c = nil
fmt.Println(*a)
答案 2 :(得分:1)
是的,完全没问题。
范围与Go在C或Rust中无关紧要。 Go是一种垃圾收集语言。只要可以访问内存,就不会释放它。在您的示例中,a
的原始值将在下一个GC期间释放,因为它不再可用。
编辑:在堆叠上。在您的程序中,b
不会逃脱,因为它不需要。如果您重写程序以便在堆栈中分配b
时将被删除(例如,like this),您将看到b
确实已逃脱。 Go的逃逸分析很聪明,可以看到这样的事情。