iOS 内存

1,138 阅读3分钟

内存布局 内核区 高地址

未初始化 高地址 栈 向下 :方法调用,

堆 向上 通过alloc分配

未初始化数据 bss 未初始化的全局变量

已初始化数据 已初始化的全局变量

代码段 程序代码

保留 低地址

——————————————————————————————————————————————

小对象 TaggerPointer NSNmuber

NONPOINTER—ISA 64位 剩余的bite位 非指针的iSA

散列表:引用计数表 弱引用表 和引用计数表

NONPOINTER—ISA 64个bite位 第一位 标注位 0 是纯iSA指针 1 存储的还有非指针型的ISA 第二位 是否有关联对象 第三位 是否有C++ 剩下的当前对象的对象的指针地址 4到15
14 到31

33位表示类对象段实际地址

magic

weakly referenced

deallocating

has sidetable rc

extra(in醋) rc 额外的引用计数

到63

散列表

sideTables() 多个siteTable 非嵌入 64个 哈西表 sidetable 结构 自旋锁 引用计数表 弱引用表

面试题 为啥不是一个sideTable 实际上如果只有一张 由于所有的对象在不同的线程操作 需要加锁数据访问安全 效率

分离锁 分拆成8个 对8个分别加锁 当A和B同时操作 可以并发操作

怎么实现快速分流 sideTable的本质是一张hash表

自旋锁 忙等的锁 适用于轻量访问 忙等 不断的查询是否呗释放 引用技术 对指针伪装操作 哈西 size t 是否有弱引用 dealloc

weak table t 哈西

mrc arc alloc retain release retainCount autorelease dealloc

arc acr是LLVM 和runtime 协作的结果 不可以调用 retain release retainCount dealloc arc 新增 weak 和srong

引用技术管理 alloc 实践 并没有加1

retain 实现 获取sideTables 获取map 当前对象的引入对象值

SiteTable &table =SideTables()[this]; size-t &refcntStorage =table refcnts[this]: refcntStorage + =SIDE-TBABLE-RC-ONE

release

SiteTable &table =SideTables()[this]; size-t &refcntStorage =table refcnts[this]: refcntStorage - =SIDE-TBABLE-RC-ONE

retainCount

SiteTable &table =SideTables()[this]; seze-t refcnt-result =1; RefcountMap::iterator it =table.refcnts.find(this); refcnt-re

dealloc 开始 objc-rootDealloc()

rootDealloc

是否可以释放; 1判断对象是否使用了非isa指针 没有 2 弱引用表 没有 3是否有关联对象 没有 4 是否涉及到C++ 没有设计 5 has-sideTable-rc 是否通过引用技术表维护 没有 才可以调用C函数直接释放 free

object dispose()实现 objc-destruxx : 如果有C++ object

关联对象移除 在系统的delloc实现 如果有关联对 会是¥移除 clearDeallocating

weak clear no lock
将指向该对象弱引用指针置为nil 从引用对象技术表擦除 table refcnys erase

弱引用管理

——weak obj1=obj 经过编译 id obj1 objc initWeak(&obj1,obj)

添加weak 变量 objc initWeak storeWeak weak register no lock

判空 老对象是no 新对象是yes 定义客局部变量

自动释放池 autoreleasePool的实现原理

AutoreleasePool 为啥可以嵌套使用

void *ctx=objc-autoreleasepoolPush(); objc-autoreleasePoolPop(ctx); objc-autoreleasePoolPush void objc-autoreleasePoolPush(void) void AutoreleasePoolPage::push(void)

objc autorelasePoolPop void objc-autoreleasePoolPop(void) void AutoreleasePoolPage::pop(void) 一次pop实际上相当于一次批量操作

自动释放池 以栈为结点 通过双向链表的形式组合而成 双向链表 <-parentPtr ->childPtr

栈 向下增长 后入先出

aytoreleasePoolPage id next AutoreleasePoolPage const parent; AutoreleasePoolPage* child; pthread-t const thread; // 和线程先对应 autoreleasePoolPage 里面

如果发生 push next 指向下一个 [obj autorelease] next 是否在栈顶 增加一个栈结点到链表上

pop操作 根据传入的哨兵对象找到对应位置

给上次push操作之后添加依次release消息

自动释放池 在runloop将要结束的时候调用AutoreleasePoopage::pop()。 多层嵌套就是可以多次插入哨兵对象 创建了一个新的page 如果当前没有满,就不用创建

在for循环alloc图片 手动插入autoreleasePlool 手动插入autoreleasePlool 原理 栈为结点双向链表

循环引用