• IOS面试题目-----oc 是如何管理内存的《Z》


    一 基本原理

       Objective-C的内存管理机制与Java那种全自动的垃圾回收机制是不同的,它本质上还是C语言中的手动管理方式,只不过稍加了一些自动方法.
       1,OC采用了引用计数(retain count)对对象内存进行管理,例如,某个对象alloc了,那么这个对象的引用计数就加1,retain时加1,当对象不需要用时就需要销毁对象,释放内存,需要对象调用release方法,release会让引用计数减1,只有引用计数消失,相当于等于0,对象才会调用dealloc真正销毁这个对象.
       OC的对象在使用完成后不能自动销毁,一定要记得释放内存.
       Class *obj = [[Class alloc]init];//对象obj引用计数加1
       Class *obj2 = obj;//两个对象指向同一块内存
       [obj hello];
       [obj release];//对象被销毁
       [obj2 hello];//错误,obj2指向的内存不存在了
       [obj2 release];//[obj release]之后,obj2是个无效指针,没有内存,不能调用方法.
       注:dealloc是自动调用,一定不能手动调用.指针赋值不会使引用计数加1.
       2,OC中引入了autorelease pool(自动释放对象池),在遵守一些规则的情况下,可以自动释放对象.新生成的对象,只要调用autorelease就行了,无需再调用release.
       autorelease pool需要手动建立,在新建一个项目时,xcode会自动创建一个,NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];NSAutoreleasePool 内部包含一个数组(NSMutableArray),用来保存声明为autorelease的所有对象,一个对象声明为autorelease,系统所做的工作就是把这个对象加入到这个数组中去.
       NSAutoreleasePool自身在销毁的时候,会遍历一遍这个数组,release数组中的每一个成员.如果此时数组中成员的retain count为1那么release之后,retain count为0,对象正式销毁,如果此时数组中成员的retain count大于1,那么release之后,retain count大于0,对象依然没有被销毁,内存就会泄露,所以一定要注意内存管理规则(见下).
       注:什么情况下创建自动释放对象池?1)在多线程里面要自己创建.2)如果代码里面有大量临时变量时最好创建自动释放对象池.
       for(int i=0;i<100;i++){
         NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
         for(int j=0;j<100000;j++){
           [NSString stringWithFormat:@"123455666"];//产生的对象是autorelease的.
         }
         [pool release];
        }
    二、规则
     1 谁创建,谁释放。如果通过alloc、new或copy来创建一个对象,那么你必须调用autorelease或在使用完成时调用release,不是你创建的,就不用你去释放。
      2  除了alloc,new或copy之外的方法创建的对象在内部都被声明了autorelease。如,[UIButton buttonWithType:].
      3  谁retain,谁release,只要你调用了retain,无论这个对象是如何生成的,你都要调用release.
    三、范式
     1 创建一个对象
       Class *obj = [[Class alloc] init];
      2 创建一个自动释放对象
       Class *obj = [[[Class alloc] init]autorelease];
      3 指针赋值给另一个指针
       Class *obj2 = obj1;
       [obj2 retain];
       [obj2 release];
      4 在一个函数中创建并返回对象,需要把这个对象设置为autorelease
       - (Class *)fun{
         Class *obj = [[[Class alloc] init] autorelease];
         return obj;
       }
      5 在子类的dealloc方法中调用基类的dealloc方法
       - (void)dealloc{
        ……
      [super dealloc];
       }
      对于属性里的内存机制请参考属性详细说明。
     
    注:不要过度依赖retaincount,有时候内部实现并不像表面那样,计数不会换我们看到的那样,例如

    MovieViewController *movie = [[MovieViewController alloc]init];

        NSLog(@"===%d",[movie.view retainCount]);//3

        NSLog(@"===%d",[movie.view retainCount]);//4

        NSLog(@"===%d",[movie.view retainCount]);//5

  • 相关阅读:
    漫谈 C++ 的 内存堆 实现原理
    我发起了一个 .Net 开源 数据库 项目 SqlNet
    谈谈 数据库原理
    论 数据库 B Tree 索引 在 固态硬盘 上 的 离散存储
    论 东坡肉 和 红烧肉 的 区别
    浅谈 操作系统原理
    引子 初识
    P2P Downloader
    利用 MessageRPC 和 ShareMemory 来实现 分布式并行计算
    MessageRPC
  • 原文地址:https://www.cnblogs.com/aggie/p/4522397.html
Copyright © 2020-2023  润新知