做什么
escapes to heap
意思是?会不会堆起来?
这意味着消息中指示的值
离开“边界”
因此,无法保证在函数外部会发生什么,因此如果值是指针或引用(但仅限于此),则必须在堆上分配指向或引用的值。
你可以想到
逃到堆里
作为调试消息,它并不表示某个变量已“重新定位”到堆中。
简单地说,
“逃到堆里”
类似于术语:
“它离开了功能”
,或
“它在函数外部传递”
.
例如,这一行:
./variable_heap_stack.go:16:24: *px escapes to heap
说价值
*px
在函数外部传递,即作为参数传递给
fmt.Printf()
在这一行中:
fmt.Printf("x: %d\n", *px)
moved to heap
,这意味着移动到堆,对吧?和上面的有什么区别?
这表示编译器决定将消息中指示的变量移到堆中,因为它可能在函数外部被引用,因此它必须在函数中生存。而且由于从函数返回时堆栈分配的值可能会变为无效,因此要使指示的变量在函数返回后有效,它必须在堆中。
Moved to heap
是一个直接的声明,您的一个变量确实被“重新定位”到堆中。
注意:“relocated”意味着变量将首先分配到堆上,实际的“relocated”在任何情况下都不会发生。
这个
y
变量是局部的,在函数返回后没有人引用它,但是仍然有一行
y escapes to heap
,为什么?
如前所述,这并不意味着
是的
重新定位到堆,它只表示
是的
在函数外部传递,即作为参数传递给
fmt.Printf()
在这一行中:
fmt.Printf("y: %d\n", y)
是的
不会因为这个而被移动到堆中,没有必要,因为它被传递到
fmt.Printf()
通过复制其价值
fmt.Printf()
将无法联系到您的
是的
局部变量。
小贴士
您可以通过
-m
两次这样:
go run -gcflags='-m -m' variable_heap_stack.go
则此命令的输出为:
./variable_heap_stack.go:8:6: can inline getPointerOfLocalVar as: func() *int { x := 10; return &x }
./variable_heap_stack.go:14:6: cannot inline heapStackTest: non-leaf function
./variable_heap_stack.go:15:28: inlining call to getPointerOfLocalVar func() *int { x := 10; return &x }
./variable_heap_stack.go:22:6: cannot inline main: non-leaf function
./variable_heap_stack.go:10:9: &x escapes to heap
./variable_heap_stack.go:10:9: from ~r0 (return) at ./variable_heap_stack.go:10:2
./variable_heap_stack.go:9:2: moved to heap: x
./variable_heap_stack.go:16:24: *px escapes to heap
./variable_heap_stack.go:16:24: from ... argument (arg to ...) at ./variable_heap_stack.go:16:12
./variable_heap_stack.go:16:24: from *(... argument) (indirection) at ./variable_heap_stack.go:16:12
./variable_heap_stack.go:16:24: from ... argument (passed to call[argument content escapes]) at ./variable_heap_stack.go:16:12
./variable_heap_stack.go:19:13: y escapes to heap
./variable_heap_stack.go:19:13: from ... argument (arg to ...) at ./variable_heap_stack.go:19:12
./variable_heap_stack.go:19:13: from *(... argument) (indirection) at ./variable_heap_stack.go:19:12
./variable_heap_stack.go:19:13: from ... argument (passed to call[argument content escapes]) at ./variable_heap_stack.go:19:12
./variable_heap_stack.go:15:28: heapStackTest &x does not escape
./variable_heap_stack.go:16:12: heapStackTest ... argument does not escape
./variable_heap_stack.go:19:12: heapStackTest ... argument does not escape
x: 10
y: 20