内存管理篇 (一):Go语言之逃逸

2023-11-06

本篇做为Go语言内存管理的第一篇文章,会从下面几个方向来讲述逃逸:

1.什么是逃逸?

2.为什么需要逃逸?

3.逃逸是怎么实现的?

一、什么是逃逸
在开始讲逃逸之前,我们先看一下,下面的两个例子。

例子1:stack.go的fun()返回的就是一个int变量。

例子2:mem.go的fun()返回的是*int变量,同时里面的返回值是&i。

源代码如下所示:

$ go tool compile -S stack.go //生成汇编语句

汇编结果分析:通过汇编可以看出来,在mem.go中的fun()中的变量i是通过newobject(XX)来生成的数据,这就说明,这个i是存储在对中。

备注:newobject(XX)函数的定义如下所示:

看到上面的例子,有没有觉得很奇怪,为什么mem.go的fun()函数中的i,明明是变量,但是却存储在堆中?

这个其实就是Go语言的逃逸,编译器通过执行静态代码的分析去决定,到底一个变量是应该分配到一个栈上面,还是需要逃逸到一个堆上面。

二、为什么需要逃逸
在分析逃逸之前,我们需要先看下Go语言中的堆。

在Go语言中,堆作为第二存储位置,Go会优先将数据存在栈里面的。堆是不会自己释放分配的内存的,需要通过GC(garbage collector)也就是垃圾收集器来回收这些分配好的内存。

Go中的栈数据,不能作为指针指向的存储位置。原因是:goroutine的栈会在栈扩容或者缩减的时候,指向不同的存储块。例子如下所示:

(摘自:https://play.golang.org/p/pxn5u4EBSI)

一旦指针指向这种栈存储位置,就会在运行的时候出现异常,而Go编译器要想解决这个问题,就会变的更复杂,所以Go的指针就不能指向栈中的存储地址。

想来这个应该也是Go逃逸的数据存储到堆中的原因了。

三、逃逸是怎么实现的
还是以mem.go作为例子,如下所示:

Output: //./mem

执行$ go build -gcflags "-m -m" mem.go 会得到下面的分析结果:

结果分析:通过输出的结果,我们可以看到line 10的 i, 会根据line 12的return &i来决定,将变量i 分配到堆上面。

 逃逸的内存分配如下所示:

1. main函数和fun函数,分别会有两个栈信息,分别为main frame和fun frame,如下图所示。

2.在fun frame中,变量i会在heap中分配对应的数据,地址为0xc000014080,变量值此时为0。

3.main函数在调用fun()之后,会copy一份i的值给变量a,此时的a的地址是0xc0000c028,存的值是i的地址0xc000014080,这个地址在堆中。

4.不管是在fun还是在main函数中,操作地址0xc000014080就可以取到对应的数值。

参考资料:
Language Mechanics On Escape Analysis:https://www.ardanlabs.com/blog/2017/05/language-mechanics-on-escape-analysis.html

Go's Memory Allocator - Overview:https://andrestc.com/post/go-memory-allocation-pt1/
————————————————
版权声明:本文为CSDN博主「灰子学技术」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhghost/article/details/104075162

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

内存管理篇 (一):Go语言之逃逸 的相关文章

  • 七. go 常见数据结构实现原理之 反射

    目录 一 golang 是如何实现反射的 如何比较两个对象完全相等 一 golang 是如何实现反射的 参考博客Go 语言问题集 Go Questions Go 语言在 reflect 包里定义了各种类型 实现了反射的各种函数 通过它们可以
  • Go项目部署及所遇问题

    小聊 本次小白给大家带来Golang项目部署操作以及个人所遇问题和解决它们的方法 依然是一边实操演示一边写文稿 如遇相似问题却存有疑惑可留言 开发环境是Window 部署环境是Linux 开发工具为GoLand 部署服务器为阿里云 1 打包
  • Go语言入门【09】结构体

    结构体 相比于Java 在Go语言中没有类的概念 但是多了结构体 结构体与Java中的类很像 是表示一系列同一类型或不同类型的数据构成的数据集合 例如可以将学生抽象成一个结构体 每一个学生有以下属性 Name 姓名 Age 年龄 Gende
  • Go语言实现区块链与加密货币-Part3(交易优化,单机模拟多节点通信)

    交易 二 在这个系列文章的一开始 我们就提到了 区块链是一个分布式数据库 不过在之前的文章中 我们选择性地跳过了 分布式 这个部分 而是将注意力都放到了 数据库 部分 到目前为止 我们几乎已经实现了一个区块链数据库的所有元素 今天 我们将会
  • 带你使用Golang快速构建出命令行应用程序

    在日常开发中 大家对命令行工具 CLI 想必特别熟悉了 如果说你不知道命令工具 那你可能是个假开发 每天都会使用大量的命令行工具 例如最常用的Git Go Docker等 不管是做技术开发还是业务开发 都会有开发命令行程序的场景 例如如果是
  • Golang-使用 goroutine 运行闭包的“坑”

    介绍 在 Go 语言中 函数支持匿名函数 闭包就是一种特殊的匿名函数 它可以用于访问函数体外部的变量 需要注意的是 在 for range 中 使用 goroutine 执行闭包时 经常会掉 坑 因为匿名函数可以访问函数体外部的变量 而 f
  • golang sleep

    golang的休眠可以使用time包中的sleep 函数原型为 func Sleep d Duration 其中的Duration定义为 type Duration int64 Duration的单位为 nanosecond 为了便于使用
  • go 进阶 gin实战相关: 五. gin_scaffold 企业脚手架

    目录 一 gin scaffold 企业级脚手架 二 gin scaffold 脚手架安装及使用演示 文件分层解释 开始使用 1 配置开启go mod 功能 2 下载 安装 gin scaffold 3 整合 golang common 4
  • Golang协程与通道整理

    协程goroutine 不由OS调度 而是用户层自行释放CPU 从而在执行体之间切换 Go在底层进行协助实现 涉及系统调用的地方由Go标准库协助释放CPU 总之 不通过OS进行切换 自行切换 系统运行开支大大降低 通道channel 并发编
  • Go语言里面的各种疑难杂症

    什么是闭包 闭包有什么缺陷 func AddUpper func int int var n int 10 return func x int int n n x return n func main f AddUpper fmt Prin
  • Go中 Redis Client的使用

    文章目录 常见操作 List 操作 Pipeline 使用 在 Go 语言中使用 Redis 时 可以使用第三方库实现 Redis Client 的封装 本文介绍如何使用 Go 语言的 redisClient 去连接 Redis 服务器 并
  • goland环境配置

    goland modules环境配置 下载和安装goland 环境配置 配置环境变量GOPATH 配置go modules GOPROXY代理的系统变量 工程目录中新建三个工作目录 goland中启用go modules 新建一个go程序
  • Golang 内存对齐视频

    https www bilibili com video BV1Ja4y1i7AF 简而言之 就是注意写代码的时候要把相同类型的元素放在一起 更进一步需要自己将结构体配对为32位或64位的整数倍 有助于减少额外空间消耗
  • go-zero开发入门之网关往rpc服务传递数据2

    go zero 的网关服务实际是个 go zero 的 API 服务 也就是一个 http 服务 或者说 rest 服务 http 转 grpc 使用了开源的 grpcurl 库 当网关需要往 rpc 服务传递额外的数据 比如鉴权数据的时候
  • go-zero开发入门之gateway深入研究1

    创建一个 gateway 示例 main go package main import flag fmt gateway middleware github com zeromicro go zero core conf github co
  • GoLong的学习之路,进阶,Viper(yaml等配置文件的管理)

    本来有今天是继续接着上一章写微服务的 但是这几天有朋友说 再写Web框架的时候 遇到一个问题 就是很多的中间件 redis 微信 mysql mq 的配置信息写的太杂了 很不好管理 希望我能写一篇有管理配置文件的 所以这篇就放到今天写吧 微
  • go开发--操作mysql数据库

    在 Go 中访问 MySQL 数据库并进行读写操作通常需要使用第三方的 MySQL 驱动 Go 中常用的 MySQL 驱动有 github com go sql driver mysql 和 github com go xorm xorm
  • Golang拼接字符串性能对比

    g o l a n g golang g o l an g
  • golang 生成一年的周数

    GetWeekTimeCycleForGBT74082005 获取星期周期 中华人民共和国国家标准 GB T 7408 2005 参数 year 年份 GB T 7408 2005 func GetWeekTimeCycleForGBT74
  • 【go语言】AST抽象语法树详解&实践之扫描代码生成错误码文档

    背景 为了能识别出代码中抛出错误码的地址和具体的错误码值 再根据错误码文件获取到错误码的具体值和注释 方便后续的排错 这里使用AST进行语法分析获取到代码中的目标对象 一 编译过程 在开始解析代码之前先补充了解一下编译过程 编译过程是将高级

随机推荐

  • Safari开发者工具

    Safari开发者工具 1 开发者功能 2 开发者功能可以干什么 2 1 捕获模拟器的请求 1 开发者功能 Safari gt 首选项 gt 高级 gt 开启 在菜单栏中显示 开发 菜单 2 开发者功能可以干什么 2 1 捕获模拟器的请求
  • Android 自定义View :虚线矩形

    预览效果 涉及参数 斜线起点坐标 斜线可以忽略 斜线终点坐标 斜线可以忽略 矩形左上角坐标 矩形右下角坐标 其中 前两个参数用于绘制预览效果中矩形上方的斜线 如果不需要可以移除 本案例涉及视频外一个点指向视频内某块区域 因此参数略微复杂 除
  • CMD 命令换行

    CMD 命令换行 在执行较长的 cmd 命令或制作 cmd 命令脚本时 为了方便编写和阅读 有时需要在命令中加入适当的换行 基于不同的命令 有两种换行方式 普通命令 在要换行的地方输入 然后回车 再继续命令的输入 控制命令 如 if for
  • 如何使实时数据采集处理系统保持数据的高速传输

    如何使实时数据采集处理系统保持数据的高速传输 1引言 当前 越来越多的设计应用领域要求具有高精度的A D转换和实时处理功能 在实时数据采集处理系统设计中 一般需要考虑数据采集以及对采集数据的处理 而对于大数据量的实时数据采集处理系统来说 保
  • Linux服务器Java输出文件中文乱码

    使用下面语句查看编码 String encoding System getProperty file encoding 结果输出 ANSI X3 4 1968 从而导致中文乱码通过 locale 查看服务器系统编码 需要修改 1在tomca
  • 【论文阅读笔记】BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

    BERT的出现使我们终于可以在一个大数据集上训练号一个深的神经网络 应用在很多NLP应用上面 BERT Pre training of Deep Bidirectional Transformers for Language Underst
  • css实现容器高度 适应 屏幕高度

    元素的高度默认是auto 被内容自动撑开 100 使得html的height与屏幕的高度相等 50 使得html的height等于屏幕的一半 若想让一个 div 的高度与屏幕高度自适应 始终充满屏幕 需要从html层开始层层添加height
  • 文本生成评估指标:ROUGE、BLEU详谈

    目录 1 自动摘要与机器翻译 1 自动摘要和机器翻译的定义和目标 2 自动摘要和机器翻译领域的挑战 2 ROUGE Recall Oriented Understudy for Gisting Evaluation 1 ROUGE 的目的和
  • AI虚拟点读机--详细注释解析恩培作品7

    感谢恩培大佬对项目进行了完整的实现 并将代码进行开源 供大家交流学习 一 项目简介 本项目最终达到的效果为手势控制虚拟点读机 如下所示 项目用python实现 调用opencv等库 使用SVM对字体进行分类 由以下步骤组成 1 使用Open
  • cd命令、pwd命令和环境变量PWD、OLDPWD的关联

    1 cd命令 cd命令这里不多介绍 cd 命令是返回上次所在的目录 2 PWD和OLDPWD环境变量 dai ubuntu env PWD home dai OLDPWD dai ubuntu 3 关联 1 当你输入 cd 命令返回上次的目
  • R语言之匹配篇

    2019独角兽企业重金招聘Python工程师标准 gt gt gt match match函数的声明如下 match x table nomatch NA integer incomparables NULL x 向量 要匹配的值 tabl
  • 深入MTK平台bootloader启动之【 Pre-loader -> Lk】分析笔记

    1 bootloader到kernel启动总逻辑流程图 ARM架构中 EL0 EL1是必须实现 EL2 EL3是选配 ELx跟层级对应关系 EL0 app EL1 Linux kernel lk EL2 hypervisor 虚拟化 EL3
  • Codeforces Round #589 (Div. 2)【数学 + 构造】

    A题 Distinct Digits 因为数的大小最长也就是5位 所以直接暴力求解即可 复杂度O 5 N include
  • C\C++ standard lib

    link
  • vue.js 解决空格报错!!!

    当我们初入vue js的时候 使用cli脚手架快速创建项目的时候 如果语法格式错误 这里主要指的是 空格多少引起的问题 找到 webpack base config js文件注释掉下面的东西 var path require path va
  • LeetCode 82. 删除排序链表中的重复元素 II

    题目链接 82 删除排序链表中的重复元素 II 设置虚拟头结点dummy不用考虑边界情况 p指针指向的是上一个没有重复的元素的位置 初始位置是dummy q从p gt next开始 一直走到第一个与q gt next不同元素的位置 删除中间
  • 经典目标检测算法—背景差分法、帧差法和三帧差法

    一 实验目的与要求 1 熟悉经典目标检测算法的原理 2 使用MATLAB语言编程实现背景差分法 帧差法和三帧差法 3 比较背景差分法 帧差法和三帧差法的特点 并了解该算法的应用条件 二 实验环境 Windows matlab 三 实验内容和
  • phpspreadsheet excel导入导出

    单个sheet页Excel2003版最大行数是65536行 Excel2007开始的版本最大行数是1048576行 Excel2003的最大列数是256列 2007以上版本是16384列 xlswriter xlswriter PHP 高性
  • Bean的四种注入方式

    1 set方法注入 2 构造器注入 3 静态工厂注入 4 实例工厂注入 我使用下面两个类来进行注入的演示 这两个类分别是User和Car类 Car类 public class Car 只包含基本数据类型的属性 private int spe
  • 内存管理篇 (一):Go语言之逃逸

    本篇做为Go语言内存管理的第一篇文章 会从下面几个方向来讲述逃逸 1 什么是逃逸 2 为什么需要逃逸 3 逃逸是怎么实现的 一 什么是逃逸 在开始讲逃逸之前 我们先看一下 下面的两个例子 例子1 stack go的fun 返回的就是一个in