close
当前位置: 物联网在线 > 技术文库 > ios >

iOS管理对象内存的数据结构以及操作算法--SideTables、RefcountMap、weak_table_t

第一次写文章语言表达能力太差。如果有哪里表达的不够清晰可以直接评论回复我,我来加以修改。这篇文章力求脱离语言的特性,咱们多讲结构和算法。即使你不懂iOS开发,不懂Objective-C语言也可以看这篇文章。

通过阅读本文你可以了解iOS管理对象内存的数据结构是什么样的,以及操作逻辑。对象的reatin、release、dealloc操作是该通过怎样的算法实现的,weak指针是如何自动变nil的。

一、引用计数的概念

这一部分是写给非iOS工程师的,便于大家了解引用计数、循环引用、弱引用的概念。如果已经了解相关概念可以直接跳过第一部分。

大家都知道想要占用一块内存很容易,咱们 new 一个对象就完事儿了。但是什么时候回收?不回收自然是不成的,内存再大也不能完全不回收利用。回收早了的话,真正用到的时候会出现 野指针 问题。回收晚了又浪费宝贵的内存资源。咱们得拿出一套管理内存的方法才成。本文只讨论iOS管理对象内存的 引用计数 法。

内存中每一个对象都有一个属于自己的引用计数器。当某个对象A被另一个家伙引用时,A的引用计数器就+1,如果再有一个家伙引用到A,那么A的引用计数就再+1。当其中某个家伙不再引用A了,A的引用计数会-1。直到A的引用计数减到了0,那么就没有人再需要它了,就是时候把它释放掉了。

在引用计数中,每一个对象负责维护对象所有引用的计数值。当一个新的引用指向对象时,引用计数器就递增,当去掉一个引用时,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源。

采用上述机制看似就可以知道对象在内存中应该何时释放了,但是还有一个 循环引用 的问题需要我们解决。

iOS管理对象内存的数据结构以及操作算法--SideTables、RefcountMap、weak_table_t

现在内存中有两个对象,A和B。

A.x = B; B.y = A;

假如A是做视频处理的,B是处理音频的。

现在A的引用计数是1(被B.y引用)。

现在B的引用计数也是1(被A.x引用)。

那么当A处理完它的视频工作以后,发现自己的引用计数是1不是0,他心里想"哦还有人需要我,我还不能被释放。"

当B处理完音频操作以后他发现他的引用计数也是1,他心里也觉得"我还不能被释放还有人需要我。"

这样两个对象互相循环引用着对方谁都不会被释放就造成了内存泄露。为了解决这个问题我们来引入 弱引用 的概念。

弱引用指向要引用的对象,但是不会增加那个对象的引用计数。就像下面这个图这样。 虚线为弱引用 (艾玛我画图画的真丑)

iOS管理对象内存的数据结构以及操作算法--SideTables、RefcountMap、weak_table_t

A.x = B; __weak B.y = A;

这里我们让B的y是一个弱引用,它还可以指向A但是不增加A的引用计数。

所以A的引用计数是0,B的引用计数是1(被A.x引用)。

当A处理完他的视频操作以后,发现自己的引用计数是0了,ok他可以释放了。

随之A.x也被释放了。( A.x是对象A内部的一个变量 )

A.x被释放了以后B的引用计数就也变成0了。

然后B处理完他的音频操作以后也可以释放了。

循环引用的问题解决了。我们不妨思考一下,这套方案还会不会有其它的问题?

思考中...

还有一个 野指针 的问题等待我们解决。

如果A先处理完他的视频任务之后被释放了。

这时候B还在处理中。

但是处理过程中B需要访问A (B.y)来获取一些数据。

由于A已经被释放了,所以再访问的时候就造成了 野指针 错误。

因此我们还需要一个机制,可以让A释放之后,我再访问所有指向A的指针( 比如B.y )的时候都可以友好的得知A已经不存在了,从而避免出错。

我们这里假设用一个数组,把所有指向A的弱引用都存起来,然后当A被释放的时候把数组内所有的若引用都设置成nil( 相当于其他语言中的NULL )。这样当B再访问B.y的时候就会返回nil。通过判空的方式就可以避免野指针错误了。当然说起来简单,下面我们来看看苹果是如何实现的。

二、抛出问题

前面絮絮叨叨说了一大堆,其实真正现在才抛出本次讨论的问题。

1、如何实现的引用计数管理,控制加一减一和释放?

2、为何维护的weak指针防止野指针错误?

三、数据结构分析( SideTables、RefcountMap、weak_table_t )

iOS管理对象内存的数据结构以及操作算法--SideTables、RefcountMap、weak_table_t

咱们先来讨论最顶层的 SideTables

iOS管理对象内存的数据结构以及操作算法--SideTables、RefcountMap、weak_table_t


(责任编辑:ioter)

用户喜欢...

从电池到传感器,完整拆解小米智能自行车

多少年来,我们一直认为:任何一台能够用电力的设备,将会最终安装上电力驱动。米家骑记电助力折叠自行车现在...


通过数据分析提高企业销售成功率,GetAccept获160万美元种子轮融资

GetAccept的联合创始人Mathias Thulin非常熟悉销售们面临的一个个常见问题:他们和潜在客户聊得非常好,也能马上用邮件...


一次下电和二次下电到底有什么区别? 如何操作?

所谓的一次下电、二次下电是针对开关电源(电源柜)说的。为什么要设置二次下电电压呢?为了保护电池组不会出...


[原创] ST STUSB4710 USB PD控制器解决方案

ST公司的STUSB4710是USB供电( PD)控制器新系列产品,不需要MCU就能连接到UFP或DRP,提供5个定制的电源数据目标(PDO),5个通用...


全球最快的嵌入式内存,宜鼎国际推出全球首款嵌入式DDR4 2666MT/s DIMM

工控与嵌入式储存解决方案领导厂商—宜鼎国际(Innodisk),今日宣布推出全球首个全系列DDR4 2666嵌入式内存模块解决...


[原创] TI TIDA-00998超低功耗能量收获和电源管理参考设计

TI公司的TIDA-00998是采用bq25505超低功耗升压充电器的超低功耗能量收获和电源管理参考设计.太阳能收获能对锂电池充电...


帮助企业优化员工健康管理,Lumity获DFJ领投1900万美元B轮融资

Lumity是一家致力于通过提供以数据为基础的推荐,帮助企业优化健康计划的创企。日前,该创企完成1900万美元B轮融资...


从分布式管理到多租户实现,企业级大数据系统如何利用开源生态构建?

作者: 陈冬 大数据系统的应用领域 首先回顾一下历史。 从中我们可以看到一些趋势,在大数据生态发展的过程中,...


三维工艺设计管理系统助力中国制造业

制造业是一个国家国际竞争力和综合实力的重要表现,工业制造业的可持续发展不仅对于国家的经济建设具有重要意...


物联网开应用法门 物流车队管理增效率

车队管理是物流业者的重要经营策略之一,就其架构来看,可说是最早成形的物联网系统,物联网前端的全面感知、...