简述一下内存逃逸?什么情况下会发生内存逃逸 ?
内存逃逸(Memory Escape)是Go语言中的一个概念,涉及到Go的内存管理和垃圾收集机制。当我们说一个对象发生了内存逃逸,意味着这个对象的生命周期不仅限于它被创建的函数,而且在函数返回后,这个对象依然可以被访问。这样的对象不能被分配在栈上,而是要在堆上进行分配。
以下是几种可能导致内存逃逸的情况:
1. 返回局部变量的指针:如果函数返回其局部变量的指针,那么这个局部变量就不能在栈上分配,因为栈空间会在函数返回后被回收。
func foo() *int {
x := 1
return &x
}
2. 将局部变量赋值给全局变量:同样,如果函数将其局部变量的引用赋值给一个全局变量,那么这个局部变量就不能在栈上分配。
var global *int
func foo() {
x := 1
global = &x
}
3. 将局部变量的引用放入到接口值、切片或者地图等数据结构中:如果函数将局部变量的引用放入到这些数据结构中,那么这个局部变量就不能在栈上分配。
func foo() {
x := 1
y := []int{2, 3, 4}
y[0] = x
}
在Go语言中,通过逃逸分析(Escape Analysis),编译器会自动决定变量应该被分配在堆上还是栈上。你可以使用go build -gcflags=-m
命令来查看编译器的逃逸分析结果。