OC 内存管理


  (一)内存管理方式
1 Crash(闪退)   90%的原因是因为内存问题
2 内存问题体现两个方面 : 内存溢出      野指针异常
2.1 iOS给每个应用程序分配了一定的内存,用于程序的运行,一旦超出内存上限,程序就会Crash
****** iPhone3GS内存30M左右,iPhone5s内存80M左右,iPhone6之后是100M左右
********3.5寸非Retina屏幕(320*480),
           一张全屏图,占用字节数 329*480*4
             一个像素占4个字节,存放RGBA,既 600 Bytes
            iPhone 3GS同时读取60张图片就会Crash


*********4寸屏幕(320*568)实际像素 640 * 11136
        一张全屏图,占用字节数 640 * 1136 *4既2.77 Mbytes
        iPhone 5s 同时读取40张图片就会Crash

********* 4.7寸屏幕(375*667)实际像素750*1334
     一张全屏图片,占用字节数750*1334*4 既3.82M Bytes
     iPhone 6 同时读取27张图片就会Crash

*********  5.5屏幕(414*736),实际像素1080*1920
     程序存放全屏图,占用字节数1080*1920*4,既7.91M bytes
     iphone 6 同时读取131张图片就会Crash
    
********* iOS6之后,系统分给每一个APP的大小是100M左右,运行期间使用内存超过这个上限,立即Crash

2.2 野指针:对象的内存已经被系统回收,但是仍然使用指针操作这块内存。
      代码量越大,程序越容易出现野指针问题
*****访问没有所有权的内存,如果想要安全的访问,必须确保空间还在
2.3 过度释放 :在同一块引用计数为1的内存释放多次。立即Crash
2.4 内存泄露 :空间使用完之后没有及时的返回系统

3 垃圾回收机制(Garbage - Collection)
     MRC(Manual Reference Counting)
     ARC(Auto Reference Counting)
垃圾回收机制:程序员只需要开辟内存空间,不需要 代码的 形式释放,系统来判断哪些空间不再被使 ,并回收这些内存 空间,以便再次分配。整个回收的过程不需要写任何代码,由 系统 动完成垃圾回收。Java开发中一直使用的就是垃圾回收 技术。

     MRC(Manual Reference Counting)
人工引用计数:内存的开辟和释放 都由程序代码进 控制。相对垃圾回收来说,对内存的控制更 加灵活,可以在需要释放的时候及时释放,对程序员的要求较 高,程序员要熟悉内存管理的机制
     ARC(Auto Reference Counting)
自动引用计数:iOS 5.0的编译器特性,它允许用户只开辟空间,不用去释放空间。它不是垃圾回收!它的本质还是MRC,只是编译器帮程序员默认加le释放的代码。

iOS 支持两种内存管理方式:ARC和MRC
MRC的内存管理机制是:引用计数
ARC是基于MRC的

  ******************************************

     内存管理黄金法则:
     如果你对一个对象做了 alloc,copy,retain操作之后,你就有了对象的所有权,你就有责任对它进行release或者autorelease
     简单来说: 只要自己使用了增加引用计数的方法,那就必须使用数量对等的减少方法,如果没有使用,和自己无关,不用处理

     (二)引用计数机制
**** C语言中,使用malloc 和 free ,进行堆内存的创建和释放
****堆内存只有正在使用和销毁两种状态
****实际开发中,可能遇到连个以上的指针使用同一块内存
****C语言无法记录内存使用者的个数

1 OC对象的操作       生成对象   持有对象           释放对象                                                销毁对象
OC中对应的方法        +alloc      -retain            -release/-autorrealease                      -dealloc 
*********************************************

让引用计数发生改变的方法:
1)   +alloc :在堆区开辟内存空间,让被开辟的内存的空间的引用计数从0 变为1
2)  -retain :将原有对象的引用计数加1
3)   -copy  : 把某一对象的内容拷贝一份,拷贝出新的对象,会在堆区开辟新的空间,原有对象的引用计数不变,新的对象的引用计数变1
4)   -release :将原有对象的引用计数立即减1
5)   -autorrelease 未来的某一时刻引用计数减1
     如果对象之前引用计数为4,autorrelease之后任然为4,未来某个时刻会变为3

*****************************************************

2  通过autoreleasepool自动释放池,控制autorelease对象的释放
向一个对象发送autorelease消息,该对象就会被添加到离 autorelease 最近的自动释放池中,当自动释放池销毁时,为池中的每个对象发送 release 消息
****iOS5 之前,使用NSAutoreleasePool 自动释放池类创建对象
     NSAutoreleasePool  *pool = [[NSAutoreleasePool alloc]init];    //自动释放池创建
                 内容
     [pool release]; //自动释放池销毁

***********在iOS5之后,不再推荐使用NSAutreleasePool 类,使用 @autoreleasepool{ }替代
     出了大括号,自动释放池才向各个对象发送release消息
     @autoreleasepool{
        自动释放池创建
     }自动释放池销毁

3   dealloc
-dealloc 是继承自父类的方法,当对象引用计数为0的时候,由对象自动调用,销毁该对象的空间
重写dealloc方法,验证对象的空间是否被回收
-(void)dealloc{
        NSLog(@“%@对象被销毁”,self);
        [super dealloc];//父类对该方法的实现才是真正的回收空间
     }

  (三)内存管理原则
1 凡是使用了alloc、retain或者copy让内存的引用计数增加了,就需要使用release或者autorelease让内存的引用计数减少。在一段代码内,增加和减少的次数要相等
2  如果增加的次数大于减少的次数,会造成内存泄露
3  如果增加次数小于减少的次数,会造成过度释放
4 如果增肌的次数等于减少的次数,还继续访问,造成野指针问题

    

原文地址:https://www.cnblogs.com/chenbowen/p/6030126.html