什么是内存逃逸?
本该在栈上分配空间的变量因为一些特别的原因,导致该变量最终在堆上分配空间,导致变量逃逸
内存逃逸的一些场景分析
1.闭包导致的内存逃逸:
在函数运行栈空间上分配的内存,由于闭包的关系,变量在函数的作用域之外使用
func closure() func() int { var a int return func() int { a++ return a } }
2.返回指向栈变量的指针:
返回的变量是栈对象的指针,编译器认为该对象在函数结束之后还需要使用
type Empty struct {} func Demo() *Empty { return &Empty{} }
3.申请大空间或者可变长空间导致的内存逃逸
申请的空间过大,也会直接在堆上分配空间/编译器无法知道需要分配多大的空间
4.返回局部引用也会导致
编译器认为返回的对象可能会在函数调用完成之后, 还会再次使用 所以, 编译器会在堆上分配内存空间
func returnMap() map[string] struct {} { return make(map[string]struct{}) } func returnSlice() [] int { return make([]int,10) }
总结:
逃逸是在编译期间完成的,主要是决定是在栈中或者堆中分配内存,在实际分析中通过go build -gcflags=-m main.go命令可以发现内存是否逃逸