这里有两部分,一个是malloc,再一个是你写的代码。
再来看你写的代码,什么是你写的代码呢?以c语言为例,.c文件就是你写的代码,这包括你写的hello world程序、充满bug的练习程序,当然还有各种项目。
接着链接器出场,连接器会把目标文件和标准库打包成可执行程序。
这就是代码部分,接下来我们看内存分配。
内存实际上和储物柜非常相似,储物柜会划分成了一个一个大小相同的隔间,每个隔间可以存储东西,内存的道理也一样,内存也被划分成了一个一个大小相同的隔间,我们来仔细看一下。
程序的运行依赖栈区,这里存放着局部变量等信息;依赖堆区,这里存放着程序员自己管理的动态申请的内存,关于堆区和栈区之前的视频也有讲解;除此之外还依赖代码区,这里保存的就是编译后的之类;还有数据区,这里保存着全局变量等信息。
这些区域在内存中的布局是这样的:
此时要分配第一块大小为A的内存,那么你应该把A放在哪里呢?
因为此时堆区是空的,显然你可以把开始这个位置划分给A,作为A的地盘,找到A的地盘后malloc这个函数返回,内存分配过程结束,是不是很简单。
接着程序员又开始申请大小为B的内存,道理和A一样,把A之后的地盘给B即可。
程序员又开始申请大小为C的内存,同理。
接着程序员说A占用的这块内存使用完毕,调用free释放,所谓释放就是把A占据的地盘重新标记为空闲,这时堆区里还有两块空闲内存。
接着程序员开始申请大小为D,这时问题来了,你该从哪里给D划分地盘呢?
放到第一个空闲块吗?显然第一个空闲块大小不够。
第二个呢,第二个也不够。
但是你发现了一个问题,仔细看着两个空闲块,这两个空闲块的总大小实际上是超过D的。
我们把这种空闲的但是不能用来分配出去的内存称之为内存碎片。
你可以想象一下经过不断的内存申请和释放,堆区中会存在无数这样空闲内存碎片。
现在堆区扩容完毕,此时就可以在堆区中找出一块合适的空闲内存分配给D,到这时malloc这个过程才真正结束,这实际上是一个相当复杂的过程。
当然这里只是一个相对简化的讲解。