使用去范围变量的内存地址是否安全?

Is it safe to use the memory address of descoped variables?

这段代码安全吗? bif 块结束时被取消作用域,但 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)
}

Go 中没有悬挂指针。

如果b超出范围也没关系; a 现在拥有该地址并将被 GC 扫描。

是的,非常好。

作用域在 Go 中并不像在 C 或 Rust 中那么重要。 Go 是一种垃圾收集语言。只要内存可以到达,它就不会被释放。在您的示例中,a 的原始值将在下一次 GC 期间被释放,因为它不再可访问。

编辑: 在堆栈中。在您的程序中, b 不会转义,因为它不需要。如果您重写您的程序,以便 b 在堆栈上分配时将被删除(例如,like this),您将看到 b 确实逃逸了。 Go的逃逸分析很聪明,能看出这种事

代码是安全的。 Go 中的任何赋值都有复制语义,所以

a = &b

等同于

c = &b
a = c

分配给参考你有效地复制了这个参考

所以这肯定也有效

b := 5
c := &b
a = c
c = nil

fmt.Println(*a)

http://play.golang.org/p/fGTYhEXl1S