gpt4 book ai didi

go - 'go run -gcflags -m xxx.go' 的输出是什么意思

转载 作者:IT王子 更新时间:2023-10-29 02:09:30 25 4
gpt4 key购买 nike

在go程序中试图检查一个局部变量是否分配在堆或栈上,并且不能确定go的gc输出的一些含义。


代码

variable_heap_stack.go:

// variable heap & stack learn,
// run with:
// go run -gcflags -m xxx.go
package main

import "fmt"

func getPointerOfLocalVar() *int {
x := 10 // go will put it into heap,
return &x
}

// heap & stack test,
func heapStackTest() {
px := getPointerOfLocalVar()
fmt.Printf("x: %d\n", *px)

y := 20 // go will put it into stack,
fmt.Printf("y: %d\n", y)
}

func main() {
heapStackTest()
}

执行:

go run -gcflags -m variable_heap_stack.go

输出:

# command-line-arguments
./variable_heap_stack.go:8:6: can inline getPointerOfLocalVar
./variable_heap_stack.go:15:28: inlining call to getPointerOfLocalVar
./variable_heap_stack.go:10:9: &x escapes to heap
./variable_heap_stack.go:9:6: moved to heap: x
./variable_heap_stack.go:16:24: *px escapes to heap
./variable_heap_stack.go:19:13: y escapes to heap
./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

问题

  • escapes to heap 是什么意思?是否要堆?
  • moved to heap,意思是移到堆上吧?和上面那个有什么区别?
  • y 变量是局部变量,函数返回后没有人引用它,但仍有一行y escapes to heap,这是为什么呢?

最佳答案

What does escapes to heap mean? Is it going to heap or not?

这意味着消息中指示的值离开了函数的“边界”,因此,无法保证在函数之外会发生什么,因此如果该值是指针或引用(但仅此而已),必须在堆上分配指向或引用的值。

您可以将 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, this means move to heap, right? What's the difference with the above one?

这表明编译器决定将消息中指示的变量移动到堆中,因为它可能在函数外部被引用,因此它必须在函数中存活。并且由于从函数返回后堆栈分配的值可能会变得无效,因此要使指示的变量在函数返回后有效,它必须在堆上。

Moved to heap 是直接声明你的一个变量确实被“重定位”到堆中。 注意:“重定位”意味着变量将被分配首先在堆上,实际的“重定位”在任何情况下都不会发生。

The y variable is local, no one refer to it after function returns, but there still got a line y escapes to heap, why was that?

如前所述,这并不意味着y被重定位到堆中,它只是将值y传递到函数外部,即作为参数传递给fmt.Printf() 在这一行:

fmt.Printf("y: %d\n", y)

y 不会因此而被移动到堆中,没有必要,因为它通过复制它的副本传递给 fmt.Printf()值,fmt.Printf() 将无法访问您的 y 局部变量。

提示:

您可以像这样传递两次 -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

关于go - 'go run -gcflags -m xxx.go' 的输出是什么意思,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51518742/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com