iOS 底层探索之路

iOS 底层探索:内存五大区

2020-11-24  本文已影响0人  欧德尔丶胡

iOS 底层探索: 学习大纲 OC篇

前言

一 、 内存五大区

在iOS中,内存主要分为栈区、堆区、全局区、常量区、代码区五大区域。如下图所示

针对4GB运存

栈区(Stack)

注:

  • iOS主线程栈大小是1MB
  • 其他主线程是512KB
  • MAC只有8M

缓冲区域

堆区(Heap)

  1. 堆是从低地址向高地址扩展。

  2. 堆是不连续的内存区域,类似于链表结构(增删快,查找慢),遵循先进先出(FIFO)原则

  3. 堆的地址空间在iOS中是以0x6开头,其空间的分配总是动态的

  4. 堆区的分配一般是在运行时分配

注:
当需要访问堆中内存时,一般需要先通过对象读取到栈区的指针地址,然后通过指针地址访问堆区

野指针:提前释放了,查询时找不到内容
内存泄露 :没有释放,一直占用内存
过度释放:对已释放的对象进行release操作。

全局静态区(.bss)

  1. 存放全局变量和静态变量
  2. 空间由系统管理。(程序启动时,开辟空间;程序结束时,回收空间;程序执行期间一直存在)在iOS中一般以0x1开头;
  3. static修饰的变量仅执行一次,生命周期为整个程序运行期

常量区(.data)

  1. 存放常量(整型、字符型,浮点,字符串等),整个程序运行期不能被改变。

2 .空间由系统管理,生命周期为整个程序运行期。在iOS中一般以0x1开头。

代码区(即.text)

内核区:

拓展

defineconst区别:

define: 宏。编译期不会进行语法识别,没有类型。编译期会分配内存。每次使用都会进行宏替换和开辟内存。

const: 常量。编译期会进行语法识别,需要指定类型。编译期不会分配内存,仅在第一次使用时,开辟内存并记录内存地址。后续调用时不会开辟内存,直接返回记录的内存地址。效率更快。内存占用更少。

内存验证

运行下面一段代码,看看变量在内存中是如何分配的

- (void)test {
    
    NSInteger i = 666;
    NSLog(@"NSInteger i -> 内存地址:%p", &i); // 【局部变量】 栈区

    NSString * name = @"QWERDF";
    NSLog(@"NSString name -> 内存地址: %p", name); // 【字符串内容】 存放在常量区
    NSLog(@"NSString name -> 指针地址: %p", &name);// 【局部变量name的指针】 存放在栈区
    
    NSObject * objc = [NSObject new];
    NSLog(@"NSObject objc -> 内存地址: %p", objc);// 【对象的内容】 存放在堆区
    NSLog(@"NSObject objc -> 指针地址: %p", &objc);//【对象的指针】 存放在栈区
}

打印结果: (0x7开头: 栈区 、 0x1开头: 常量区、 0x6开头: 堆区)

2020-11-02 11:19:39.121235+0800 001---- 内存验证[5104:87115] NSInteger i -> 内存地址:0x7ffeeb3e0668 (栈区)
2020-11-02 11:19:39.124740+0800 001---- 内存验证[5104:87115] NSString name -> 内存地址: 0x10481f0e0(常量区)
2020-11-02 11:19:39.128252+0800 001---- 内存验证[5104:87115] NSString name -> 指针地址: 0x7ffeeb3e0660(栈区)
2020-11-02 11:19:39.143804+0800 001---- 内存验证[5104:87115] NSObject objc -> 内存地址: 0x600002fc07d0(堆区)
2020-11-02 11:19:39.145034+0800 001---- 内存验证[5104:87115] NSObject objc -> 指针地址: 0x7ffeeb3e0658(栈区)
上一篇下一篇

猜你喜欢

热点阅读