内存管理

一、内存布局

  • stack:方法调用
  • heap:经过alloc等分配内存
  • bss:未初始化的全局变量等
  • data:已初始化的全局变量等
  • text:程序代码

二、内存管理方案

  • TaggedPointer
  • NONPOINTER_ISA
  • 散列表
散列表

三、数据结构

  • Spinlock_t "忙等"锁,轻量访问
  • RefcountMap
    size_t
  • weak_table_t

四、MRC / ARC

  • MRC alloc/retain/release/retainCount/autorelease/dealloc
  • ARC LLVM和Runtime协做; ARC中禁止手动调用retain/release/retainCount/dealloc; 新增strong/weak属性关键字

五、引用计数

  1. alloc,最终调用calloc,此时引用计数为0
  2. retain实现
SideTable& table = SideTables()[this];
size_t& refcntStorage = table.refcnts[this];
refcntStorage += SIDE_TABLE_RC_ONE;
复制代码
  1. release实现
SideTable& table = SideTables()[this];
RefcountMap::iterator it = table.refcnts.find(this);
it->second -= SIDE_TABLE_RC_ONE;
复制代码
  1. retainCount实现
SideTable& table = SideTables()[this];
size_t refcnt_result = 1;
RefcountMap::iterator it = table.refcnts.find(this);
refcnt_result += it->second >> SIDE_TABLE_RC_SHIFT;
复制代码

5.dealloc 数据结构

object_dispose()
objc_destructInstance()

clearDeallocating()

6. 弱引用

{
    id __weak obj1 = obj;
}

{
    id obj1;
    objc_initWeak(&obj1, obj);
}
复制代码

七、自动释放池

void *ctx = objc_autoreleasePoolPush();
...
objc_autoreleasePoolPop(ctx);
复制代码
void *objc_autoreleasePoolPush(void) <=> void *AutoreleasePoolPage::push(void)

void objc_autoreleasePoolPop(void* ctx) <=> AutoreleasePoolPage::pop(void* ctx)
复制代码
  • 以栈为结点经过双向链表的形式组合而成
  • 和线程一一对应

  • RunLoop将要结束时调用AutoreleasePoolPage::pop()
  • 多层嵌套就是屡次插入哨兵对象
  • for循环中含有内存消耗较大的场景时,如图片对象的建立,手动插入AutoreleasePool

八、循环引用

分类
  • 自循环引用
  • 相互循环引用
  • 多循环引用
存在的场景
  • 代理
  • Block
  • NSTimer
  • 大环引用
解决方案
  • __weak
  • __block: MRC下,__block修饰的对象不回增长引用计数,避免循环引用; ARC下,__block修饰的对象会被强引用,没法避免循环引用,须要手动解环
  • __unsafe_unretained:修饰对象不会增长引用计数,避免循环引用;可是被修饰对象被释放时,会产生悬垂指针
NSTimer循环引用问题

相关文章
相关标签/搜索