美文网首页OC学习
OC的内存管理机制

OC的内存管理机制

作者: 李小六_ | 来源:发表于2015-05-10 12:54 被阅读439次
    1. 为什么要使用内存管理

    iOS应用程序出现crash(闪退), 90%以上的原因是出现了内存问题!
    内存问题主要出现在内存溢出和野指针异常!

    内存溢出 iOS给每个应用提供了一定的内存, 用于程序的运行, 一旦超过内存的上限,就会Crash,
    野指针异常 对象内存空间已经被系统回收, 然而去还用指针指使用了这块内存!

    2. 内存管理的分类

    垃圾回收机制(gc);
    垃圾回收机制: 程序员只需要开辟内存空间, 不需要用代码去释放! 系统自己来判断那些空间不再被使用, 并且回收这些内存空间以便再次分配, 整个回收的过程不需要写任何代码, 有系统自动完成垃圾回收, java开发中一直使用的就是垃圾回收机制!

    MRC(Manual Reference Count) ; 人工引用计数;
    人工引用计数: 内存的开辟和释放都是由程序代码进行控制, 相对于垃圾回收机制来说,对内存的控制更加灵活, 可以在需要释放的饿时候及时释放, 对程序员的要求较高, 程序员要熟悉内存的管理的机制!

    ARM (Auto Reference Count);
    自动引用计数:iOS 5.0的编译器特性, 它允许用户开辟空间, 不用去释放空间, 它不是垃圾回收! 她的本质还是MRC, 只是编译器帮程序员默认加了释放的代码,
    iOS 支持MRC和ARC

    3. 引用计数

    C语言中,使用malloc 和 free 进行堆内存, 进行堆内存的创建和释放, 对内存只有正在使用和销毁两种状态!
    实际开发中, 可能遇到两个以上的指针使用同一块内存, C语言无法记录内存使用个数!
    OC采用引用计数管理内存, 当一个新的引用指向对象的时候, 引用计数器就递增, 当去掉一个引用时, 引用计数就递减, 当引用计数, 到零的时候, 该对象就是占有的资源!

    OC引用技术的方法
    • alloc 引用计数+1;
      Person *p = [[Person alloc] init];
      // 显示引用计数
      NSLog(@"%ld", [p retainCount]); // 引用计数 1

    • retain 引用计数+1
      [p retain];
      NSLog(@"%lu", [p retainCount]); // 引用计数 2;

    • release 引用计数 -1
      [p release];
      NSLog(@"%lu", [p retainCount]); 引用计数 1;

    但是, 当p再次release一次的时候,
    [p release] // -1 此时p的引用计数为0, 因而对象应该是已被释放的!
    NSLog(@"%lu", [p retainCount]); 打印却为1;
    打出的引用计数虽然为1, 但他的实际为零, 对象已经被释放的!

    • autorelease autorelease引用计数不是立即 -1, 在未来的某一时刻(出了 autoreleasepool(自动释放池)) 之后, 引用计数再 -1**

    通过autoreleasepool控制autorelease对象的释放!
    向一个对象发送autorelease消息, 这个对象何时释放, 取决于autoreleasepool(自动释放池子)!

      Person *p2 = [[Person alloc] init]; 
      @autoreleasepool {
      [p2 retain]; 引用计数+1 为2;
      [p2 autorelease]; 此时引用计数为2;
      NSLog(@"%lu", [p2 retainCount]);
      }
    

    NSLog(@"%lu", [p2 retainCount]); // 出了释放池, 计数 -1

    • copy 引用几计数 +1
      对象想使用copy, 必须签订copy协议, 实现copy协议
      person类签订copy协议, 实现copy方法

    如下.h 和 .m 文件
    Person .h 文件
    // 签订copy协议
    #import
    @interface Person : NSObject <NSCopying>
    @property(nonatomic, assign)NSString *name;
    @property(nonatomic, assign)NSString *age
    @end

    Person  .m文件  // 必须重写delloc方法, 因为
      #import "Person.h"
      @implementation Person
      // 重写alloc方法
      - (void)dealloc
      {
      NSLog(@"******"); // 定义一个, 用于标记
      [super dealloc];
       }
      // 实现copy协议方法
      - (id)copyWithZone:(NSZone *)zone
      {
      Person *p = [[Person allocWithZone:zone]  init];
      p.name = self.name;
      p.age = self.age;
      return p;
      }
    

    调用!
    Person *p3 = [[Person alloc] init];
    p3.name = @"tom";
    p3.age = @"20";
    // 使用copy创建
    Person *p4 = [p3 copy];
    NSLog(@"--- %d ---", LINE);
    NSLog(@"%@, %@", p4.name, p3.age);
    NSLog(@"%lu", [p3 retainCount]);
    // p4 的引用计数是多少?
    NSLog(@"%lu", [p4 retainCount]); // 用copy 计数 会+1;

    • dealloc
      • dealloc是继承自父类的方法,当对象引用计数为0的时候,由对象自动调用。用于释放内存区域;
      • 必须重写delloc方法, 在.m文件中
    • 加入数组的时候, 对象retain一次, 引用计数+1;
      Person *p5 = [[Person alloc] init];
      [arr addObject:p5];
    • 对象移除数组的时候, 对象release一次, 引用计数 -1;
      [arr removeObject:p5];
      添加和删除, 系统内部都帮你实现了!
    内存管理原则;
    - 引用计数的增加和减少相等,当引用计数降为0之后,不应该再使 用这块内存空间;
    - 凡是使用了alloc、retain或者copy让内存的引⽤用计数增加了,就需要使用release或者autorelease让内存的引用计数减少。在一段代码内,增加和减少的次数要相等。 
    

    相关文章

      网友评论

        本文标题:OC的内存管理机制

        本文链接:https://www.haomeiwen.com/subject/izqafttx.html