- 内存分配方式
- 逃逸分析
- 总结
一、内存分配方式
一个执行的程序在内存中的分配总共有五部分:
1、text:存储程序的二进制指令和一些静态内容
2、data:存储已经初始化的全局变量,静态分配
3、bss:存储未被初始化的全局变量,静态分配
4、stack:栈,主要用来函数调用时存储局部变量。内存由系统管理,通过压栈的方式自动分配和通过出栈的方式自动释放。
5、heap:堆,用于动态分配内存,由垃圾回收器管理。
Golang的分配方式主要是栈分配和堆分配。
栈分配廉价,堆分配昂贵。
- 栈:可以只通过压栈和出栈两个CPU指令来实现栈空间的分配和释放,属于静态分配内存。
- 堆:使用堆进行动态分配后,在释放堆空间时,需要使用垃圾回收器来扫描寻找堆空间中不再被使用的对象。
使用栈分配:函数内部的局部变量未被外部引用,即变量在编译期间便可确定作用域。
只能使用堆分配:(1)函数内部的局部变量被外部引用。(2)当变量需要申请的内存过大而超过栈的存储能力时。
二、逃逸分析
通过命令 go build -gcflags ‘-m’ ./main.go
,可以多传几个-m
来查看更详细的内容,-l
可以禁止内联优化。
指针逃逸:一个对象的指针被多个线程或方法引用。
逃逸分析:Golang编译器分析指针对象动态范围的方法。逃逸分析决定了变量的内存分配在栈或是堆。
编译器通过在编译时进行垃圾回收的工作来选择某个变量的内存分配方式。编译器通过追踪变量在代码块中的作用域,变量携带的校验数据可以验证其生命周期在运行时是否完全可知,如果是,便可以在栈上分配内存。否则称该变量逃逸,只能通过堆来分配内存。
引起变量逃逸到堆上的典型情况:
1、发送指针或带有指针