Objective-C内存管理 | 青训营笔记

85 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的的第5天。

今天整理了上课的系统内存管理部分,内存管理一直是我学习的不够透彻的部分,明日继续深入学习。

Objective-C内存管理

背景介绍

Heap & Stack

  • Stack(栈)

    • Pop(销毁)➕ Push(存储)

    • 存储参数/局部变量/函数调用后返回地址,线程安全

    • Stack Pointer

      • 指向栈顶
      • 一般存储在寄存器
    • 高地址向低地址扩展

  • Heap(堆)

    • 与Heap数据结构无关
    • 手动分配
    • 向高地址扩展
    • 存储数组和对象,线程共享

C内存管理

malloc➕free

C++内存管理

  1. new➕delete
  • malloc➕free与new➕delete

    • malloc/free只是动态分配内存空间/释放空间

      new/delete 还会调用构造函数和析构函数进行初始化与

    • malloc/free需要手动计算类型大小

      new/delete可自动计算类型的大小

    • malloc/free管理内存失败会返回0

      new/delete等的方式管理内存失败会抛出异常。

  1. Smart Pointer 智能指针

    🌟保留 -> 和 * 运算符

    🌟auto_pt & unique_ptr

    • 两个指针不能指向同一个资源
    • 无法进行左值unique_ptr复制构造,也无法进行左值复制赋值操作,但允许临时右值赋值构造和赋值

🌟shared_ptr

可以复制赋值操作 创造对象(control block中的引用计数)

Reference Counting 引用计数

  • 记录了当前内存资源到底有多少指针在引用(可以访问这个资源)
  • 当新增加一个可以访问这个资源的引用,计数器会加1,反之会减去1
  • 当引用计数= 0时, 对象会被销毁

iOS内存管理

核心是管理(强)引用计数 (Reference Counting)

当前代码只需要考虑ARC

管理什么?

  • 继承NSObject对象会分配在堆里面
  • 任何继承NSObject对象都需要内存管理

为什么要管理?

  • 多个对象之间相互强引用,导致不能释放,无法让系统回收
  • 如果一个程序占用内存过多,系统可能会强制关闭程序,造成crash
  • 如果提前释放指针,会导致野指针,也会造成crash

术语:持有 = retain = 引用计数 +1 释放 = release = 引用计数 -1

MRC Manual Reference Counting

OC中,使用引用计数来进行内存管理,每个对象都有一个相应的引用计数

  • “alloc”, “new”, “copy”, or “mutableCopy” 开头的方法创建的对象,引用计数 = 1
  • 当持有(retain)一个对象,这个对象的引用计数就会递增(+1)
  • 当这个对象的某个持有被释放(release),这个对象的引用计数就会递减(-1)
  • 当这个对象的引用计数变为0,那么这个对象就会被系统回收,系统向对象发送dealloc【不能直接调用 dealloc】

Autorelease-Pool(自动释放池)

  • 对象会放到自动释放池,统一释放
  • autorelease和release的区别是:

    • release是马上释放对某个对象的强引用;
    • autorelease是延迟释放某个对象。
  • 在部分场景下,使用Autorelease pool可以降低内存峰值

ARC(Automatic Reference Counting)

编译器自动加入内存管理代码

  • retain/release都不用考虑

    • 只需要初始化的时候 [NSObject alloc] init]
    • 可以自定义 dealloc
    • 只需要负责对象的创建即可
    • 不需要手动维护引用计数
  • 只要有一个强指针在内存指向对象,对象就不能释放

    • ARC 销毁时机是强引用的个数 = 0
    • 而不是引用计数 = 0
  • 默认所有对象变量的指针都是强指针

    • 弱指针需显式声明