GO语言内存逃逸图文分析

在分析内存逃逸之前我们需要知道我们的内存空间的分布图,为内存逃逸的分析做一些铺垫,这是内存分布,当系统知道变量什么时候的生命周期和内存分配大小的时候我们都将其分配在栈区

在这里插入图片描述

(必知)分析内存逃逸之前我们需要几个知识点:

1.go在编译阶段确立逃逸,并不是在运行时

2.Golang 中的变量只要被引用就一直会存活,存储在堆上还是栈上由内部实现决定而和具体的语法没有关系。

3.逃逸分析是编译器用于决定变量分配到堆上还是栈上的一种行为

内存逃逸基本情况有6种,我们一种一种来进行分析

情况1:指针逃逸:

我个人理解是:指针逃逸的出现场景和c++中悬空指针的场景比较相似,但似乎由于语言的差别,又有所差别。

在这里插入图片描述
在这里插入图片描述

在go语言中,相同的场景,由于我们的go语言的特点,我们的这个引用不会在栈中被消除,而是存活到了堆区,见下图

在这里插入图片描述

所以在栈上释放内存的时候不会将c释放掉,c发生了逃逸。

结论:如果一个函数结束之后外部还有引用,那么必定被分配在堆中

情况2:栈空间不足逃逸

栈空间充足情况(见下图)

在这里插入图片描述

那么我们分配的空间大于栈区怎么办(不会分配失败,而是直接分配在堆区)

在这里插入图片描述

在分配时不能栈空间确定大小,不知道到底要开辟的空间是否超出限制也会发生逃逸

在这里插入图片描述

情况3:动态类型逃逸,interface类型可以代表任意类型,编译器不知道参数会是什么类型,只有运行时才知道,因此只能分配到堆上。

在这里插入图片描述

情况4,切片由于append操作,导致容量变大,就会被分配在堆上面

在这里插入图片描述

情况5,向chan中发送数据的指针或者包含指针的值,因为不知道什么时候被释放(根据自己的理解来写的,可能不太对,不过应该能解释过去,等笔者去查阅查阅资料再来补充)

在这里插入图片描述

*情况6:slices 中的值是指针的指针或包含指针字段。一个例子是类似[] string 的类型。这总是导致 slice 的逃逸。即使切片的底层存储数组仍可能位于堆栈上,数据的引用也会转移到堆中。(只知道结论,不知道为什么,待定,以后补充)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言中,内存逃逸指的是当一个对象的指针被多个方法或线程引用时,这个指针逃逸到堆上。内存逃逸的位置由编译器决定,而不像C或C++可以使用malloc或new在堆上分配内存。根据内存分配的基本原则,当函数外部对指针没有引用时,优先分配在栈上;当函数外部对指针存在引用时,优先分配在堆上;当函数内部分配一个较大对象时,优先分配在堆上。\[1\] 在Go语言中,内存逃逸分析可以通过一些规则来判断。例如,当使用等号=赋值时,如果Data和Field都是引用类型的数据,则导致Value逃逸。另外,一些特定的数据类型也导致逃逸,比如\[\]interface{}、map\[string\]interface{}、map\[interface{}\]interface{}、map\[string\]\[\]string、map\[string\]*int、\[\]*int、func(*int)、func(\[\]string)、chan \[\]string等。具体的规则可以参考引用\[2\]中的示例。\[2\] 此外,栈空间不足也可能导致内存逃逸。当在函数中创建一个较大的切片或数组,并且栈空间不足以容纳它们时,这些切片或数组逃逸到堆上。例如,在一个函数中创建一个长度为10000的切片,如果栈空间不足,这个切片就逃逸到堆上。\[3\] 总结来说,内存逃逸是指当一个对象的指针被多个方法或线程引用时,这个指针逃逸到堆上。在Go语言中,内存逃逸的位置由编译器决定,可以通过一些规则和栈空间的判断来进行分析。 #### 引用[.reference_title] - *1* [golang内存逃逸分析](https://blog.csdn.net/qq_42170897/article/details/127770234)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [golang内存逃逸](https://blog.csdn.net/wanghao3616/article/details/107284523)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [golang——内存逃逸机制](https://blog.csdn.net/weixin_45627369/article/details/127163797)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值