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

如图所示我们可以看到,内存除了内核区与保留区,我们平时用到的分为五大区域,地址由高到低分别是栈区, 堆区, 未初始化数据区, 已初始化数据区, 代码段区,下面我们分别来介绍这五大区域。
栈区(stack)
栈区一般存放函数, 方法, 指针, 局部变量, 参数等。栈区的内存一般通过 sp
寄存器去定位。而堆区需要先通过寄存器定位到指针,再通过指针定位到指定的堆区域,所以栈区的速度相对于堆区的速度是非常非常的快的。
堆区(heap)
一般需要开辟空间来存储的都会放到堆区,例如我们通过 clloc
, new
等创建出来的对象,一般需要的空间比较大。例如我们的结构体,需要一大段空间来容纳成员变量。
未初始化数据区, 已初始化数据区, 代码段区
当 App
开始加载的时候数据都是存放在未初始化数据区, 已初始化数据区, 代码段区这三个地方,只有程序真正运行的时候才会开辟堆区空间。程序的加载主要就是控制这三块区域。
// 未初始化数据
static int bssA;
static NSString *bssStr1;
// 已初始化数据
static int bssB = 10;
static NSString *bssStr2 = @"cooci";
.bss
与 .data
统称为全局区,但是他们分为已初始化数据与未初始化数据,如代码中 bssA
与 bssStr1
为未初始化数据,没有被赋值, bssB
与 bssStr2
为已初始化数据。我们应该也都听过讲 “static
修饰过的成员变量不在内存”,其实这个说法是不严谨的,只是 static
修饰过的成员变量只是在全局区,不占用对象申请开辟的空间。代码段为程序代码,加载到内存中。

如图是我们用 MachOView
工具读取的一个 MachO
文件,可以看到section
部分的数据段跟代码段的结构。
补充
内核区
假设总共有 4GB
的内存,系统保留了 1GB
供内核使用,剩下的 3GB
供外部使用,内核主要做一些消息间的转发处理及一些系统级别的控制。
保留区
系统保留一些低地址空间来做一些 nil
等下层字段的处理。
各内存区域开头地址
- 栈区内存地址一般为:0x7 开头
- 堆区内存地址一般为:0x6 开头
- 数据段, BSS 内存地址一般为:0x1 开头
网友评论