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)

用户喜欢...

电源管理集成电路(PMIC)如何减少这些挑战的影响

在设计具有现场可编程门阵列(FPGA)的系统时,系统设计人员可以获得三个好处:可重编程性,性能可扩展性和快速上市时间。但是,设计师也必须克服挑战。在这篇文章中,我将讨论电源管...


LTC设计说明:带有数字电源系统管理的6A单片同步DC / DC降压转换器

数字电源系统管理(PSM)控制器通常针对高电流负载点(POL)应用。低电流应用,高达6A的负载电流,也可以受益于PSM功能。LTC3815是一款具有数字电源监控功能的6A单片式同步降压型转换器。...


物联网设备的超低功耗管理

据估计,物联网每年将产生数百兆字节(兆亿兆字节)的数据,而这个数字只是在增加。一般家庭对这个数字的贡献数量预计到2020年将增长五倍。创建数据并不需要太多的计算能力,因为可以...


苛刻的环境挑战电源管理

基于数据的预测建模为工业系统监控提供了极大的节约成本的可能性,这将进一步促进工厂和制造业的自动化,并协助翻新运输和能源传输基础设施。对数据的需求将要求工业界用与物联网(...


[原创] TI TIDA-01501 450W高效电源参考设计

TI公司的TIDA-01501是450W高效AC/DC转换器,AC输入85V-265V,多路DC输出12-V/5-V/3.3-V,最大输出功率450W.设计电路包括前端连续模式...


管理混合云环境的5个要点

大多数企业都意识到了采用云计算的好处,那么企业将业务迁移到混合云管理平台的最佳实践是什么呢?...


鱼与熊掌兼得,既要云服务创新也要管理传统网络

对于很多企业来说,软件即服务(SaaS)等云计算解决方案的效率显著提高、资本支出显著降低。但是真正从云技术中寻...


[原创] T PWD13F60高密度600V功率驱动器解决方案

ST公司的PWD13F60是集成了栅极驱动器和四个N沟功率MOSFET(双半桥配置)高密度功率驱动器.功率MOSFET有320 mΩ的RDS(on)和600...


[原创] ADI AD8452模拟前端控制器和SMPS PWM驱动器解决方案

ADI公司的AD8452是单一的硅芯片平台,集成了精密模拟前端控制器和开关电源(SMPS)脉宽调制器(PWM)驱动器,以实现大规模电...


[原创] Rohm BD99954应用处理器锂电池充电管理方案

Rohm公司的BD99954是1到4节锂电池双模式充电管理器,小型5.0x5.0mm QFN封装和2.6x3.0mm芯片级CSP封装,提供双源电池充电器,两个...