GO语言局部变量堆、栈分析

C语言的局部变量内存分配在栈空间,因为函数返回后,系统自动回收了函数里定义的局部变量,所以运行时去访问一个被系统回收后的地址空间,一定就会发生段错误,这是C/C++语言的特点。

GO语言局部变量逃逸分析

先看一段代码:

package main
import (
    "fmt"

)
func newInt() *int {
    var i int =4
    fmt.Println(&i)
    return &i   //为何可以返回局部变量呢?
}
func main() {
    someInt := newInt()
    fmt.Println(someInt)
    fmt.Println(*someInt)//这里不会像C,报错段错误提示,而是成功返回变量的值

}

代码输出:

0xc000062080
0xc000062080
4

参考go FAQ里面的一段话:

How do I know whether a variable is allocated on the heap or the stack?

From a correctness standpoint, you don't need to know. Each variable in Go exists as long as there are references to it. The storage location chosen by the implementation is irrelevant to the semantics of the language.

The storage location does have an effect on writing efficient programs. When possible, the Go compilers will allocate variables that are local to a function in that function's stack frame. However, if the compiler cannot prove that the variable is not referenced after the function returns, then the compiler must allocate the variable on the garbage-collected heap to avoid dangling pointer errors. Also, if a local variable is very large, it might make more sense to store it on the heap rather than the stack.

In the current compilers, if a variable has its address taken, that variable is a candidate for allocation on the heap. However, a basic escape analysis recognizes some cases when such variables will not live past the return from the function and can reside on the stack.

意思是说go语言编译器会自动决定把一个变量放在栈还是放在堆,编译器会做逃逸分析(escape analysis),当发现变量的作用域没有跑出函数范围,就可以在栈上,反之则必须分配在堆。所以不用担心会不会导致memory leak,因为GO语言有强大的垃圾回收机制。go语言声称这样可以释放程序员关于内存的使用限制,更多的让程序员关注于程序功能逻辑本身。

对于动态new出来的局部变量,go语言编译器也会根据是否有逃逸行为来决定是分配在堆还是栈,而不是直接分配在堆中。

结论

函数内部局部变量,无论是动态new出来的变量还是创建的局部变量,它被分配在堆还是栈,是由编译器做逃逸分析之后做出的决定。

声明:sunansheng 发表于 2019-04-24 17:05:00 ,共计373字。

转载请署名:GO语言局部变量堆、栈分析 | www.sunansheng.com

你可能感兴趣的:(Go语言)