在C中
int *stackref()
{
int val;
return &val;
}
val是栈上的局部变量,返回其指针是明显错误的。
而go的编译器则会进行逃逸分析,如下代码
func stackref() *int {
var val int
return &val
}
使用 go tool compile -S -m -l
输出汇编
test.go:4: moved to heap: val
test.go:5: &val escapes to heap
"".stackref t=1 size=64 value=0 args=0x8 locals=0x10
0x0000 00000 (main.go:3) TEXT "".stackref(SB), $16-8
0x0000 00000 (main.go:3) MOVQ (TLS), CX
0x0009 00009 (main.go:3) CMPQ SP, 16(CX)
0x000d 00013 (main.go:3) JLS 50
0x000f 00015 (main.go:3) SUBQ $16, SP
0x0013 00019 (main.go:3) FUNCDATA $0, gclocals·5184031d3a32a42d85027f073f873668(SB)
0x0013 00019 (main.go:3) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0013 00019 (main.go:4) LEAQ type.int(SB), BX
0x001a 00026 (main.go:4) MOVQ BX, (SP)
0x001e 00030 (main.go:4) PCDATA $0, $0
0x001e 00030 (main.go:4) CALL runtime.newobject(SB)
0x0023 00035 (main.go:4) MOVQ 8(SP), BX
0x0028 00040 (main.go:5) MOVQ BX, "".~r0+24(FP)
0x002d 00045 (main.go:5) ADDQ $16, SP
0x0031 00049 (main.go:5) RET
0x0032 00050 (main.go:5) NOP
0x0032 00050 (main.go:3) CALL runtime.morestack_noctxt(SB)
0x0037 00055 (main.go:3) JMP 0
可以看到,编译器检测到了val的逃逸,调用runtime.newobject分配在了堆上。