内存是怎样一步步被分配出来的?Python客栈共 2665字,需浏览 6分钟 ·2024-06-27 11:50 将Python客栈设为“星标⭐” 第一时间收到最新资讯 大家好,今天简单聊聊内存分配。 我们申请一块内存时计算机内部发生了什么?看下这句代码: 这里有两部分,一个是malloc,再一个是你写的代码。 malloc实际上属于标准库,标准库里有什么呢? 数学相关的函数,sin、cos、绝对值、数幂函数等;字符相关函数,判断大小写等;字符串操作函数、字符串拷贝、拼接比较等;当然还有内存管理函数,就是这里提到的malloc/free,当然还有很多其它函数,这就是标准库。 再来看你写的代码,什么是你写的代码呢?以c语言为例,.c文件就是你写的代码,这包括你写的hello world程序、充满bug的练习程序,当然还有各种项目。 这就是你写的代码。 这些代码怎么变成最终的可执行程序呢?当然是借助编译器。 编译器会把你的代码编译成目标文件。 接着链接器出场,连接器会把目标文件和标准库打包成可执行程序。 这就是代码部分,接下来我们看内存分配。 到底什么是内存呢? 内存实际上和储物柜非常相似,储物柜会划分成了一个一个大小相同的隔间,每个隔间可以存储东西,内存的道理也一样,内存也被划分成了一个一个大小相同的隔间,我们来仔细看一下。 内存中的每个隔间存储的是一个字节,8比特位一字节。 比如这里申请的一块int大小的内存,一个int占据4个字节。 和储物柜一样,内存中的每个隔间也有一个编号,这个编号叫做内存地址。 在我们的实例中,申请的这块内存位于内存地址2这个位置,这意味着什么嗯?这意味着变量p等于数字2,或者说等于内存地址2,这里的p就是所谓的指针。 接着我们看内存分配过程。 这段代码当然属于编译后生成的可执行程序,可执行程序是在内存中运行的,当然我们需要为整个程序分配一块内存。 程序的运行依赖栈区,这里存放着局部变量等信息;依赖堆区,这里存放着程序员自己管理的动态申请的内存,关于堆区和栈区之前的视频也有讲解;除此之外还依赖代码区,这里保存的就是编译后的之类;还有数据区,这里保存着全局变量等信息。 这些区域在内存中的布局是这样的: 再次强调下,编译后的代码位于代码区,malloc动态申请的内存位于堆区,接下来我们只关注堆区。 在程序开始运行时堆区当然是空的,那么所谓的内存分配到底是什么呢?如果让你实现内存分配器该怎么做到呢?很简单,其实内存分配就是划分地盘。 此时要分配第一块大小为A的内存,那么你应该把A放在哪里呢? 因为此时堆区是空的,显然你可以把开始这个位置划分给A,作为A的地盘,找到A的地盘后malloc这个函数返回,内存分配过程结束,是不是很简单。 接着程序员又开始申请大小为B的内存,道理和A一样,把A之后的地盘给B即可。 程序员又开始申请大小为C的内存,同理。 接着程序员说A占用的这块内存使用完毕,调用free释放,所谓释放就是把A占据的地盘重新标记为空闲,这时堆区里还有两块空闲内存。 接着程序员开始申请大小为D,这时问题来了,你该从哪里给D划分地盘呢? 放到第一个空闲块吗?显然第一个空闲块大小不够。 第二个呢,第二个也不够。 但是你发现了一个问题,仔细看着两个空闲块,这两个空闲块的总大小实际上是超过D的。 我们把这种空闲的但是不能用来分配出去的内存称之为内存碎片。 你可以想象一下经过不断的内存申请和释放,堆区中会存在无数这样空闲内存碎片。 碎片化的内存显然不利于内存的充分利用,计算机科学历史上有无数论文试图来解决这个问题。 现在堆区已经不足以为D申请出内存,该怎么办呢? 让我们回到最初的布局,注意看堆区和栈区中间实际上还有一段空闲内存区域,这块区域就是为堆区或栈区来扩大地盘用的,那么该怎么扩大堆区呢? 这就要借助操作系统的帮助了。 在linux等系统中可以借助brk等系统调用向操作系统申请来扩大堆区。 现在堆区扩容完毕,此时就可以在堆区中找出一块合适的空闲内存分配给D,到这时malloc这个过程才真正结束,这实际上是一个相当复杂的过程。 往期回顾 1、requirements.txt要被抛弃了? 2、Windows核弹级漏洞,Win7-Win11全部沦陷! 3、240万亿巨量数据被洗出,足够训出18个GPT-4! 4、提拔你,还是干掉你,从来不是看技术 5、彭博社:华为与腾讯接近达成协议,不向微信“抽成” 点击关注公众号,阅读更多精彩内容 浏览 39点赞 评论 收藏 分享 手机扫一扫分享分享 举报 评论图片表情视频评价全部评论推荐 “蘑菇书”是怎样磨出来的?Datawhale0阿里出来的同事,是如何一步步把公司搞乱的?开发者技术前线0微软、IBM们的中国研究院是怎样一步步“躺平”的?硅谷密探0编程语言是怎么被实现出来的?作为程序员我们经常被问这个是怎么实现的,那个是怎么实现的,可是你知道经常使用的编程语言是怎么被实现出来的吗?今天就聊聊这个问题。聪明的人类发现把简单的开关组合起来可以表达复杂的bool逻辑,在此基础之上构建了 CPU ,因此 CPU 只能简单的理解开关,用数字表达就是0和1。创世纪:聪明的笨蛋CPUJava技术迷0图解 Go 内存管理器的内存分配策略AlwaysBeta0nedmalloc内存分配模块nedmalloc是一个可选的malloc内存分配的实现,主要是适应多线程无锁操作,基于dlmalloc2.8.3。下图是性能比较:nedmalloc内存分配模块0nedmalloc内存分配模块nedmalloc内存分配模块0图解|malloc内存分配Linux内核那些事0写一个java字符串时,内存是如何分配的?程序员考拉0张小龙:产品经理是不可以被培训出来的Kevin改变世界的点滴0点赞 评论 收藏 分享 手机扫一扫分享分享 举报