按照内存地址从高(0xffffffff)到低(0x00000000)的顺序排列,可分为5大分区:栈区 -> 堆区 -> 全局静态区 -> 常量区 -> 代码区。大致分布如下图所示👇

-
栈区
- 栈区的内存空间由
系统管理--> 即方法调用开始时开辟空间,方法调用结束时回收空间。 - 栈区是从
高地址向低地址扩展,是一块连续的内存区域,遵循先进后出,后进先出(FILO)原则,使用效率高。 - 栈区的内存空间是在
运行时由系统进行分配。 - 哪些变量是栈区的?例如
方法的入参,内部定义的局部变量等,都存放在栈区。
- 栈区的内存空间由
-
堆区
- 最大的特点 --> 空间大,需程序员自己手动管理。(当然,在ARC时代也是系统自动管理的)
- 堆区是从
低地址向高地址扩展,与栈区相反,遵循先进先出(FIFO)的原则。 - 堆区由系统api开辟空间(c/c++ -->
malloc、calloc、realloc, oc -->allocnew),这个空间可以是不连续的,以链表结构存在, - 开辟出的空间的
首地址是在栈区,例如LGPerson *person = [[LGPerson alloc] init];这个person指向所指向的地址是在栈区。 - 内存回收 -->
free回收,做了两件事,一是释放堆区的内存,二是将栈区的指针置为nil。
-
全局静态区
- 存放
全局变量和静态变量。 - 内存空间也是由
系统管理-->程序启动时开辟,程序结束时回收,程序执行期间一直存在。 -
static修饰的变量仅执行一次,生命周期为整个程序运行期。
- 存放
-
常量区
- 存放
常量👇(整型、字符型,浮点型,字符串等),整个程序运行期不能被改变。-
已初始化的全局变量 -
已初始化的静态变量
-
- 空间由
系统管理,生命周期为整个程序运行期。
- 存放
-
代码区
- 存放程序执行的
CPU指令,一种二进制文件。(编译期将代码转换为CPU指令)
- 存放程序执行的
补充概念
- 内存泄漏(memory leak):是指申请的内存空间使用完毕之后未回收。
一次内存泄露危害可以忽略,但若一直泄漏,无论有多少内存,迟早都会被占用光,最终导致程序crash。(因此,开发中我们要尽量避免内存泄漏的出现)- 内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间供其使用。
通俗理解就是内存不够用了,通常在运行大型应用或游戏时,应用或游戏所需要的内存远远超出了你主机内安装的内存所承受大小,就叫内存溢出。最终导致机器重启或者程序crash。
简单来说:
| 概念 | 区别说明 |
|---|---|
| 内存泄漏 | 供应方(操作系统)能提供给需求方(App)的内存越来越少。 |
| 内存溢出 | 需求方(App)需要的内存过大,超过供应方(操作系统)负载。 |
