理解内存管理

来源:互联网 发布:犀牛地方门户源码官网 编辑:程序博客网 时间:2024/05/22 16:48

1.引用计数

1.1什么是引用计数 , 原理是什么

 引用计数可以有效的管理对象生命周期,当我们创建一个新对象的时候, 它的引用计数为1,当有一个新的指针指向这个对象的时候,我们将其引用计数加1,当某个指针不在指向这个对象的时候,我们将其引用计数减1,当对象的引用计数为1时候,说明这个对象不再被任何指针指向了,这个时候我们就可以将对象销毁,回收内存。



                                          

                                                    

                                                                               这个图很明确的表示了,引用计数的增减问题


引用技术真正派上用场的场景是在面向对象的程序设计架构中,用于对象之间的传递和共享数据。

假如对象A生成一个对象M,需要调用对象B的某一个方法,将对象M作为参数传递过去,在没有引用计数的情况下,一般的内存管理的原则是''谁申请谁释放“,那么对象A就必须要在对象B不需要对象M的时候,将对象M销毁掉,但是对象B可能只是临时用一下对象M,也可能觉得对象M很重要,将他设置成自己的一个成员变量,在这种情况下,什么时候销毁对象M就成了一个难题,

                                                 

                                                  

这个对象,就把它的引用计数加1,使用完了之后再把引用计数减1,所有对象都遵守这个规则的话,对象的生命管理就可以完全交给引用计数了,我们也可以很方便的享受到共享对象带来的好处。

不要向已经释放的对象发送消息,该对象的内存如果已经被回收,那我们向这个对象发送一个retainCount 消息,所有它的输出结果应该是不确定的,如果该对象所占用的内存被复用,那么就有可能造成程序的异常奔溃.

那为什么在这个对象被回收的之后,不确定的值是1而不是0?这是因为当执行最后UI次执行release 的时,系统知道马上就要回收内存,就没必要再讲retainCount 减1了,因为不管减不减1,该对象都肯定被回收,而对象被回收后,他的所有内存区域,包括retainCount值也变的没有意义,不将这个值从1变为0,可以减少一次内存的操作,加速对象的回收。

循环引用的问题

引用计数这种管理内存的方式虽然简单,但是有一个比较大的瑕疵,即它不能很好的解决循环引用的问题;如下图所示,对象A和对象B,相互引用对方作为自己的成员变量,只有当自己销毁时,才会将成员变量的引用计数减1,因为对象A的销毁依赖于对象B的销毁,而对象B的销毁与依赖于对象A的销毁,这样就造成了我们称之为循环引用的问题,即使在外界已经没有任何指针能够访问到他们了。他们也无法释放。



                                                        


解决循环引用的方法有2个:  第一个方法是我明确知道这里会存在循环引用,在合理的位置主动断开环的一个引用,使得对象得以回收。

第二种方法:使用弱引用,这种方法一般比较多


弱引用虽然持有对象,但是并不增加引用计数,这样避免了循环引用的产生。

在Xcode的菜单栏选择    'Prodect'->'Profile',然后选择‘Leaks’,再单机'Profile'按钮开始检测.


0 0