什么是內存逃逸?
本該在棧上分配空間的變量因為一些特別的原因,導致該變量最終在堆上分配空間,導致變量逃逸
內存逃逸的一些場景分析
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命令可以發現內存是否逃逸