OC浅谈内存管理

为什么要进行内存管理

由于移动设备的内存是及其有限的,所以每个APP所占的内存也是有限制的,当APP所占用的内存较多时,系统就会发出内存警告,此时需要回收一些不再需要使用的内存空间,比如回收一些不再使用的对象和变量等。

内存的管理范围:任何继承NSObject的对象,对其他的基本数据类型无效。

内存的本质原因:因为对象和其他数据类型在系统中的存储空间不一样。其他局部变量主要存放于栈中,而对象存放于堆中,当代码块结束时这个代码块中的所有局部变量都会被回收,指针对象的指针也被回收,此时对象已经没有指针指向,但是依然存在于内存中,这样就会造成内存泄漏。

内存中的五大区域
  • 栈:局部变量。当局部变量的作用域被执行之后,这个局部变量就会被系统立即回收。
  • 堆:OC对象。使用C函数申请的空间。直到程序结束时才会被回收。
  • BSS段:未初始化的全局变量、静态变量。一旦初始化就被回收,并转存到数据段中。
  • 数据段:已经初始化的全局变量、静态变量。直到程序结束的时候才会被回收。
  • 代码段:代码。程序结束的时候,系统会自动回收存储在代码段中的数据。

注意:

1.栈、BSS段、数据段、代码段存储在他们中的数据的回收,是由系统自动完成的,不需要我们手动干预。
2.存储在堆中的OC对象,系统不会自动回收。

内存管理的分类

  • MRC:Manuall Reference Counting,手动计数器,手动管理内存,iOS 5之前使用。(当多1个人使用对象的时候,要求程序员手动发送retain消息,少一个人使用的时候程序员手动的发送release消息)
  • ARC:Automatic Reference Counting,自动引用计数,自动管理内存,iOS 5推出的新功能,Xcode7开始系统默认支持的是ARC内存管理机制。(系统自动的在合适的地方发送retain、release消息)

因为Xcode7开始默认支持ARC内存管理机制,所以如果要关闭ARC开启MRC的话,步骤

点击这个项目的TARGETS,点击Build settings,接着在右上角搜索输入Automatic,发现在Apple Clang - Language - Objective - C下显示了Objective - C Automatic Reference Counting,将选项处的Yes改成NO,就说明已经关闭了ARC内存管理机制,从而开启了MRC内存管理机制。

在这里插入图片描述

引用计数器的作用

判断对象要不要回收的唯一依据就是引用计数器是否为0,若不为0则存在,为0的话就是对象的内存已经被回收了,对象已经不存在了。

引用计数器的相应操作

给对象发送消息,进行相应的计数器操作:
1.发送retain消息:引用计数器+1(表示该对象多一个人使用)
2.发送release消息:引用计数器-1(表示该对象该对象少一个人使用)
3.retainCount:获取对象当前的引用计数。(若引用计数为0时,表示该对象被回收)

注意

  • 当创建并初始化一个对象时,默认它的引用计数为1,当这个对象的引用计数0时,系统会自动回收这个对象,在系统回收对象的时候,会自动的调用系统的dealloc方法。
  • 重写dealloc方法时的规范:必须要调用父类的dealloc方法[super dealloc],并且这句代码要放在最后一行。
  • 在ARC内存管理机制下,retain、release、dealloc这些方法都无法使用。

内存管理的原则:

  • 有对象的创建,就要匹配一个release。
  • retain的次数要和release的次数一致。
  • 谁用谁retain,谁不用谁release。
  • 只有在多一个人使用的时候才retain,少一个人使用的时候才release。

总结:

有始有终,有加就有减,有retain就应该匹配一个release,一定要平衡。

野指针和僵尸对象

  • C语言中的野指针:定义一个指针变量,没有初始化。这个指针变量的值是一个垃圾值,指向一块随机的内存空间,这个指针就叫做野指针。
  • OC中的野指针:指针指向的对象已经被回收了。
  • 僵尸对象:一个已经被释放的对象,但是这个对象所占的空间还没有分配给别人。(所占内存已经被回收的对象)

注意

  • 我们通过野指针去访问僵尸对象的时候,有可能是有问题的,也有可能是没有问题的。
  • 当僵尸对象占用的空间还没有分配给别人的时候,这是没问题的。
  • 当僵尸对象占用的空间已经分配给别人的时候,这个是会有问题的。(编译器会报错显示僵尸对象错误)
  • 系统是不会默认打开僵尸对象检测的。(因为打开僵尸对象检测及其消耗性能)
  • 如果需要开启僵尸对象检测的话,步骤:
    点击Edit Scheme,在Run运行期这一栏点击Diagnostics(诊断结论),接着找到Zombie Objects这个选项,将它勾选上,僵尸对象检测就开启了。
    在这里插入图片描述
    在这里插入图片描述
如何避免僵尸对象报错
  • 当一个指针为野指针后,将这个指针的值设置为nil。当一个指针的值为nil,通过这个指针去调用对象的方法(包括使用点语法)的时候,不会报错,只是没有任何反应。但是如果通过指针直接访问属性(p1->_name = @“Jack”)的话,就会报错。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 当1个对象使用release方法,这个对象的引用计数已经为0时,不能使用retain方法重新去复活一个僵尸对象。(无法复活一个僵尸对象)

内存泄露

1个对象没有被及时回收,在该回收的时候没有被回收,一直驻留在内存中,直到程序结束的时候才被回收。

内存管理代码规范

  • setter方法的代码规范:
- (void)setCar:(Car *)car {
    //1.判断新旧对象是否为同一个对象
    if (_car != car) {
        //2.对旧对象做一次release
        [_car release];//若没有旧对象,则没有影响
        //3.对新对象做一次retain
        _car = [car retain];
    }
    _car = car;
}
  • dealloc方法的代码规范:
-(void)dealloc {
  //  NSLog(@"人死了");
    [_car release];
    [super dealloc];
}

注意
我们内存管理的范围是OC对象,所以,只有属性的对象是OC对象的时候,这个属性的setter方法才要想上面那样写,如果属性不是OC对象的,setter方法直接赋值就可以了。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值