golang的内存逃逸
堆内存与栈内存的区别
- 栈内存由系统进行分配与释放,堆内存由程序自身进行申请与释放
- 栈内存一般存放函数参数、函数返回值、局部变量、函数调用时的临时上下文,堆内存一般存放全局变量
- 栈内存的访问速度比堆内存快
- 每个线程分配一个栈内存,每个进程分配一个堆内存
- 栈内存创建时,内存大小固定,越界发生stack overflow,堆内存创建时大小不固定,可随程序运行进行增加或减少
- 栈内存是由高地址向低地址增长,堆内存是由低地址向高地址增长
go的内存管理
- golang对内存管理是由golang自己进行处理的,程序会在启动时向系统申请一块较大的内存,然后由golang自己决定将变量分配到栈还是堆
- 分配选择:基本原则同上面区别中所描述,不同的是对函数的引用参数的处理,如果编译器无法证明函数返回之后变量是否仍然被引用,此时就必须将该变量分配到堆内存上,然后通过垃圾回收机制进行管理,避免指针悬空。另外局部变量过大,也会被分配到堆内存,例如大切片
栈内存
- 栈内存的分配与释放全权由操作系统决定,开发者无法控制。一般栈内存会自动创建,函数返回的时候内存会被自动释放。栈内存的分配与释放速度较快
堆内存
- 对存有由于不确定大小,因此代价就是分配速度较慢且会形成内存碎片。堆内存不能自动被编译器释放,只能通过垃圾回收器才能释放
内存逃逸
- 把函数内的局部变量通过指针形式返回
- 发送指针或带有指针的值到channel中
- 在切片中存储指针或带指针的值
- Slice的底层数组被重新分配。比如使用append向容量已满的Slice追加元素,会重新为Slice分配底层数组
- 在interface类型上调用方法。因为interface类型调用方法都是动态调度,只有在运行的时候才能知道真正的实现
This blog is under a CC BY-NC-SA 3.0 Unported License
本文链接:https://alpherjang.github.io/2023/08/30/golang%E7%9A%84%E5%86%85%E5%AD%98%E9%80%83%E9%80%B8/