首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >“go run -gcflags -m xxx.go”的输出是什么意思?

“go run -gcflags -m xxx.go”的输出是什么意思?
EN

Stack Overflow用户
提问于 2018-07-25 12:20:04
回答 1查看 2.9K关注 0票数 3

尝试检查局部变量是分配在堆上还是在go程序中的堆栈上,并且无法确定go的gc的某些输出的含义。

代码

variable_heap_stack.go:

代码语言:javascript
复制
// 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()
}

执行:

运行-gcflags -m variable_heap_stack.go

输出:

代码语言:javascript
复制
# 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,为什么呢?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-07-25 13:41:52

escapes to heap是什么意思?它要堆还是不堆?

这意味着消息中指示的值保留了函数的“边界”,因此不能保证它在函数之外发生了什么,因此如果值是指针或引用(但只有到那时),则必须在堆上分配指向值或引用值。

您可以将escapes to heap 看作调试消息,它并不表示您的一个变量被“重新定位”到堆中.

所以简单地说,“转义到堆”类似于术语:“它离开了函数”,或者“它是在函数之外传递的”。

例如,这一行:

代码语言:javascript
复制
./variable_heap_stack.go:16:24: *px escapes to heap

表示*px值是在函数之外传递的,即作为此行中fmt.Printf()的一个参数:

代码语言:javascript
复制
fmt.Printf("x: %d\n", *px)

moved to heap,这意味着移动到堆,对吗?上面那个有什么区别?

这表明编译器决定将消息中指示的变量移到堆中,因为它可能被引用在函数之外,因此它必须在函数中生存下来。而且,由于一旦从函数返回堆栈分配的值可能会变得无效,如果指定的变量在函数返回后是有效的,那么它必须在堆上。

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

y变量是本地的,函数返回后没有人引用它,但是仍然有一行y escapes to heap,为什么呢?

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

代码语言:javascript
复制
fmt.Printf("y: %d\n", y)

y不会仅仅因为这个而被移到堆中,没有必要,因为它是通过复制它的值传递给fmt.Printf()的,并且fmt.Printf()将无法到达您的y局部变量。

提示:

通过这样两次传递-m,您可以获得更多关于优化决策和转义分析的详细信息:

代码语言:javascript
复制
go run -gcflags='-m -m' variable_heap_stack.go

然后,该命令的输出将是:

代码语言:javascript
复制
./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
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51518742

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档