OC底层探索21-内存五大区域

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声明的变量有什么区别?

  • 相同点都是可以进行常量的定义;
  • 区别:
    1. define在预编译阶段进行代码的替换,每使用一个位置就需要进行一次内存的开辟;
    2. const声明的变量是存放在常量区,在编译阶段就生成了,所以只需要进行一次内存的开辟,后续使用直接返回内存地址,比较节省内存;
    3. define是可以进行代码段的注入;

你可能感兴趣的:(OC底层探索21-内存五大区域)