OC底层探索21-内存五大区域
2021-06-29 本文已影响0人
Henry________
iOS设备中,内存被人为的分成5大区域
:栈区、堆区、全局/静态区、常量区、代码区
,所占内存都为系统分配的虚拟内存
。
布局结构如图:
1、栈区
- 函数内部定义的
局部变量和方法的参数
(方法中默认参数:self、cmd),都存放在栈区; - 栈区的内存空间由
系统管理
,申明的变量过了作用域范围后内存便会自动释放; - 栈是
一块连续的内存区域
从从高地址向低地址
进行存储,遵循FILO先进后出
原则。 - iOS主线程栈大小是1MB
- 方法的调用也是在栈中进行;
1.1 栈区特点
- 优点:快速高效,开发人员无需关注其内存的释放;
- 缺点:数据有限制且不够灵活(数据大小与生存期必须是确定的)。
2、堆区
- 一般是由
alloc、malloc
等内存分配方式创建的变量; - 开发人员需要关注变量的生命周期。如果不及时释放,会造成内存泄漏,只有等程序结束时由系统统一回收;
- 堆是
不连续的内存区域
,类似于链表结构
(便于增删,不便于查询),遵循先进先出(FIFO)原则;
2.1 栈区特点
- 优点:获得空间灵活,分配内存较大;
- 缺点:容易造成碎片(链表结构);
3、全局/静态区
- 该区域的变量是系统在程序编译时生成,退出时销毁。
生命周期为整个程序运行期
- BSS段:没有初始化的全局/静态变量存储在这个区域;
- DATA段:用于存储已经初始化的全局/静态变量;
4、常量区
- 该区域的变量是系统在程序编译时生成,退出时销毁。
生命周期为整个程序运行期
- 存放常量:
整型、字符型,浮点,字符串等
,用const
进行修饰的变量;
5、代码区
- 代码会被编译成二进制存进内存的代码区域;
验证
NSLog(@"字符串地址:%p",@"constq3123");
NSLog(@"常量地址:%p",&constStr);
static NSString *staticStrUn;
static NSString *staticStr = @"constq3123";
NSLog(@"静态变量地址:%p",&staticStr);
NSLog(@"未初始化静态变量地址:%p",&staticStr);
HRTest * test = [HRTest alloc];
NSLog(@"对象地址:%p",test);
NSLog(@"局部变量指针地址:%p",&test);
-(void)say{
NSLog(@"方法参数self:%p",&self);
NSLog(@"方法参数cmd:%p",&_cmd);
}
输出:
通过一些简单的方式进行验证。
区域验证
- 借助MachOView可以窥探一二,对比地址发现代码区的地址是最小的;
一则面试题
问:define和const声明的变量有什么区别?
- 相同点都是可以进行常量的定义;
- 区别:
- define在
预编译阶段
进行代码的替换,每使用一个位置就需要进行一次内存的开辟; - const声明的变量是
存放在常量区
,在编译阶段就生成了,所以只需要进行一次内存的开辟,后续使用直接返回内存地址
,比较节省内存; - define是可以进行代码段的注入;
- define在