go 如何知道一个对象是分配在栈上还是堆上?

如何判断变量是分配在栈(stack)上还是堆(heap)上?

Go和C++不同,Go局部变量会进行逃逸分析 。如果变量离开作用域后没有被引用 ,则优先分配到栈上,否则分配到堆上。判断语句:

Go 复制代码
// -m打印逃逸分析信息, -l禁止内联编译
go build -gcflags '-m -m -l' xxx.go 

通常情况下:

栈上 :函数调用的参数、返回值以及小类型局部变量大都会被分配到栈上,这部分内存会由编译器进行管理。无需GC标记

堆上大对象、逃逸的变量 会被分配到堆上。分配到堆上的对象,Go在运行时GC会在后台将对应的内存进行标记 ,从而能够在垃圾回收的时候将对应的内存回收,进而增加了开销

例子:

Go 复制代码
func main() {
	a := make([]int, 10000)
	b := make([]int, 1000)
    print(a,b)
}

可以看到

a 由于无法被一个执行栈装下,即使没有返回,也会直接在堆上分配;
b 能够被一个执行栈装下,变量没有返回到栈外,进而没有发生逃逸,分配到栈中


指针逃逸分析

局部变量以指针的方式从方法中传出或被全局变量引用 ,这种现象被称为指针逃逸(Escape).

情况一(最基本):在某个函数中new或字面量创建出的变量,将其指针作为函数返回值,则该变量一定发生逃逸

Go 复制代码
func main() {
	c := call2()
    print(c)
}
func call2() *int {
	x := 2
	return &x
}

情况二:指针作为函数调用参数,则该变量如果没有被逃逸的变量或者全局变量引用,指针不会逃逸

Go 复制代码
func main() {
	a := make([]int, 5)
	call(&a)
}

func call(a *[]int) {
	(*a)[0] = 1
}

情况三:仅在函数内 对变量做取值操作 ,而未将指针传出 ,指针不会逃逸

Go 复制代码
func main() {
	a := 2
	b := &a
    print(b)

情况四:指针作为函数调用参数 ,则该变量如果被逃逸的变量或者全局变量引用指针会逃逸

Go 复制代码
var g *int

func main() {
	a := 2
	g = &a
}

情况五:被指针类型的slice、map和chan引用的指针一定会发生逃逸

Go 复制代码
func main() {
	a := make([]*int, 1)
	b := 12
	a[0] = &b

	c := make(map[string]*int)
	d := 14
	c["aaa"] = &d

	e := make(chan *int, 1)
	f := 15
	e <- &f
}

总结

golang 变量存储在堆上还是栈上由内部实现决定而和具体的语法没有关系。非指针小对象通常保存在栈上,大对象保存在堆上。至于指针保存在堆上还是栈上,要进行逃逸分析:

指针必然发生逃逸的三种情况:

  • 在某个函数中new或字面量创建出的变量,将其指针作为函数返回值,则该变量一定发生逃逸(构造函数返回的指针变量一定逃逸);
  • 被已经逃逸的变量引用的指针,一定发生逃逸;
  • 被指针类型的slice、map和chan引用的指针,一定发生逃逸;

一些必然不会逃逸的情况:

  • 指针被未发生逃逸的变量引用;
  • 仅仅在函数内对变量做取址操作,而未将指针传出;
相关推荐
胡萝卜3.04 小时前
深入理解string底层:手写高效字符串类
开发语言·c++·学习·学习笔记·string类·string模拟实现
西柚小萌新4 小时前
【Python从入门到精通】--Pycharm增加内存
开发语言·python·pycharm
不爱编程的小九九4 小时前
小九源码-springboot082-java旅游攻略平台
java·开发语言·旅游
只是懒得想了4 小时前
用C++实现一个高效可扩展的行为树(Behavior Tree)框架
java·开发语言·c++·design-patterns
yan8626592464 小时前
于 C++ 的虚函数多态 和 模板方法模式 的结合
java·开发语言·算法
Small___ming4 小时前
【Python基础】Python路径操作全解析:os.path、glob与pathlib从入门到精通
开发语言·python
_poplar_5 小时前
15 【C++11 新特性】统一的列表初始化和变量类型推导
开发语言·数据结构·c++·git·算法
lly2024065 小时前
Ruby Socket 编程
开发语言
i学长的猫5 小时前
Ruby小白学习路线
开发语言·学习·ruby
生信小窝5 小时前
068B-基于R语言平台Biomod2集成模型的物种分布模型构建和数据可视化教程【2027】
开发语言·信息可视化·r语言