内存管理-内存布局

在我们开发过程中基本时时刻刻都会跟内存打交道,那么在底层内存又是如何分布的呢?相信这也是大家比较想知道的,下面我们就来介绍下。

如图所示我们可以看到,内存除了内核区与保留区,我们平时用到的分为五大区域,地址由高到低分别是栈区, 堆区, 未初始化数据区, 已初始化数据区, 代码段区,下面我们分别来介绍这五大区域。

栈区(stack)

栈区一般存放函数, 方法, 指针, 局部变量, 参数等。栈区的内存一般通过 sp 寄存器去定位。而堆区需要先通过寄存器定位到指针,再通过指针定位到指定的堆区域,所以栈区的速度相对于堆区的速度是非常非常的快的。

堆区(heap)

一般需要开辟空间来存储的都会放到堆区,例如我们通过 clloc, new 等创建出来的对象,一般需要的空间比较大。例如我们的结构体,需要一大段空间来容纳成员变量。

未初始化数据区, 已初始化数据区, 代码段区

App 开始加载的时候数据都是存放在未初始化数据区, 已初始化数据区, 代码段区这三个地方,只有程序真正运行的时候才会开辟堆区空间。程序的加载主要就是控制这三块区域。

// 未初始化数据
static int bssA;
static NSString *bssStr1;
// 已初始化数据
static int bssB = 10;
static NSString *bssStr2 = @"cooci";

.bss.data 统称为全局区,但是他们分为已初始化数据与未初始化数据,如代码中 bssAbssStr1 为未初始化数据,没有被赋值, bssBbssStr2 为已初始化数据。我们应该也都听过讲 “static 修饰过的成员变量不在内存”,其实这个说法是不严谨的,只是 static 修饰过的成员变量只是在全局区,不占用对象申请开辟的空间。代码段为程序代码,加载到内存中。

如图是我们用 MachOView 工具读取的一个 MachO 文件,可以看到section 部分的数据段跟代码段的结构。

补充

内核区

假设总共有 4GB 的内存,系统保留了 1GB 供内核使用,剩下的 3GB 供外部使用,内核主要做一些消息间的转发处理及一些系统级别的控制。

保留区

系统保留一些低地址空间来做一些 nil 等下层字段的处理。

各内存区域开头地址

  • 栈区内存地址一般为:0x7 开头
  • 堆区内存地址一般为:0x6 开头
  • 数据段, BSS 内存地址一般为:0x1 开头
作者:晨曦_iOS

%s 个评论

要回复文章请先登录注册