zoukankan      html  css  js  c++  java
  • 内存管理(MRC与ARC)

    内存管理

         ARC: Automatic(自动) Reference(引用) Counting(计数)

         什么是自动引用计数?

         不需要程序员管理内容, 编译器会在适当的地方自动给我们添加release/retain等代码

         注意点: OC中的ARCjava中的垃圾回收机制不太一样, java中的垃圾回收是系统干得, OC中的ARC是编译器干得

         

         MRC: Manul(手动) Reference(引用) Counting(计数)

         什么是手动引用计数?

         所有对象的内容都需要我们手动管理, 需要程序员自己编写release/retain等代码

         

         内存管理的原则就是有加就有减

         也就是说, 一次alloc对应一次release, 一次retain对应一次relese

    野指针和空指针

                        只要一个对象被释放了, 我们就称这个对象为 "僵尸对象"

            当一个指针指向一个僵尸对象, 我们就称这个指针为野指针

            只要给一个野指针发送消息就会报错

            // *** -[Person release]: message sent to deallocated instance 0x1001146b0

            空指针  nil  0

             为了避免给野指针发送消息会报错, 一般情况下, 当一个对象被释放后我们会将这个对象的指针设置为空指针

            因为在OC中给空指针发送消息是不会报错的

    MRC

    1. 【掌握】内存管理原则

    2. 【掌握】多对象内存管理

    3. 【掌握】set方法内存管理

    4. 【掌握】dealloc方法的内存管理

    1.内存管理原则

    - 苹果官方规定的内存管理原则

        + 谁创建谁release :

            * 如果你通过alloc、new、copy或mutableCopy来创建一个对象,那么你必须调用release或autorelease

        + 谁retain谁release:

            * 只要你调用了retain,就必须调用一次release

    - 总结一下就是

        + 有加就有减

        + 曾经让对象的计数器+1,就必须在最后让对象计数器-1

    ---

    2.多对象内存管理

    - 单个对象的内存管理, 看起来非常简单

    - 如果对多个对象进行内存管理, 并且对象之间是有联系的, 那么管理就会变得比较复杂

    - 其实, 多个对象的管理思路 跟很多游戏的房间管理差不多

        + 比如斗地主 劲舞团 QQ音速

    ![](images/a5/534347_001415_6_lit.jpg)

    - 总的来说, 有这么几点管理规律

        + 只要还有人在用某个对象,那么这个对象就不会被回收

        + 只要你想用这个对象,就让对象的计数器+1

        + 当你不再使用这个对象时,就让对象的计数器-1

    3.set方法内存管理

    - (1)retain需要使用的对象

    - (2)release之前的对象

    - (3)只有传入的对象和之前的不同才需要release和retain

    - (void)setRoom:(Room *)room

    {

        // 避免过度释放

        if (room != _room)

        {

            // 对当前正在使用的房间(旧房间)做一次release

            [_room release];

     

            // 对新房间做一次retain操作

             _room = [room retain];

        }

    }

    4.dealloc方法的内存管理

    - (void)dealloc

    {

        // 当人不在了,代表不用房间了

        // 对房间做一次release操作

        [_room release];

        [super dealloc];

    }

    ARC

    ARC机制下有几个明显的标志:

        +  不允许调用对象的 release方法

        +  不允许调用 autorelease方法

        +   再重写父类的dealloc方法时,不能再调用 [super dealloc];

    ARC下单对象内存管理

    - 局部变量释放对象随之被释放

     默认情况所有指针都是强指针

     弱指针需要明确说明

        + 注意: 千万不要使用弱指针保存新创建的对象

    .ARC下多对象内存管理

    - ARC和MRC一样, 想拥有某个对象必须用强指针保存对象, 但是不需要在dealloc方法中release

     

    .ARC下循环引用问题

    - ARC和MRC一样, 如果A拥有B, B也拥有A, 那么必须一方使用弱指针

     

    ARC下@property参数

    - strong : 用于OC对象, 相当于MRC中的retain

    - weak : 用于OC对象, 相当于MRC中的assign

    - assign : 用于基本数据类型, 跟MRC中的assign一样

    问题1:什么是堆?什么是栈?

    答:

    • 栈(操作系统):由操作系统自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈(先进后出);
    • 堆(操作系统):一般由程序员分配释放,若程序员不释放,程序结束时可能由系统回收,分配方式类似于链表。

    问题2:什么是内存管理?

    答: 所谓内存管理, 就是对内存进行管理, 涉及的操作有:

    • 分配内存 : 比如创建一个对象, 会增加内存占用
    • 清除内存 : 比如销毁一个对象, 能减小内存占用

    问题3:内存管理的本质是什么?

    答:

    • OC对象存放于堆里面
    • 非OC对象一般放在栈里面(栈内存会被系统自动回收)

    2.引用计数器和dealloc基本概念

    问题1:什么是引用计数器?

    答:每个OC对象都有自己的引用计数器,它是一个整数,表示有多少人正在用这个对象

    问题2:引用计数器的作用?

    答:

    1. 当使用alloc、new或者copy创建一个对象时,对象的引用计数器默认就是1
    2. 当对象的引用计数器为0时,对象占用的内存就会被系统回收
    3. 如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收(除非整个程序已经退出 )

    问题3:怎么操作引用计数器?

    答:

    • 给对象发送一条retain消息,可以使引用计数器值+1(retain方法返回对象本身
    • 给对象发送一条release消息, 可以使引用计数器值-1
    • 给对象发送retainCount消息, 可以获得当前的引用计数器值
    • 需要注意的是: release并不代表销毁回收对象, 仅仅是计数器-1

    问题4:dealloc 方法的作用?

    答:

    • 对象即将被销毁时系统会自动给对象发送一条dealloc消息
    • (因此, 从dealloc方法有没有被调用,就可以判断出对象是否被销毁)

    3.单个对象内存管理

    问题1:什么是ARC?什么是MRC?

    答:

    1.ARC: Automatic(自动) Reference(引用) Counting(计数)

    什么是自动引用计数?

    不需要程序员管理内容,编译器会在适当的地方自动给我们添加release/retain等代码

    • 注意点: OC中的ARC和java中的垃圾回收机制不太一样, java中的垃圾回收是系统干得, 而OC中的ARC是编译器干得

    2.MRC: Manul(手动) Reference(引用) Counting(计数)

    什么是手动引用计数?

    所有对象的内容都需要我们手动管理, 需要程序员自己编写release/retain等代码

    问题2:重写dealloc方法有什么注意点?

    答: 重写dealloc方法, [super dealloc]一定要写到所有代码的最后

    4.野指针和空指针

    问题1:什么是僵尸对象?什么是野指针?什么是空指针?如何避免野指针错误?

    答:

    1. 僵尸对象 已经被销毁的对象(不能再使用的对象)

    2.野指针 指向僵尸对象(不可用内存)的指针 给野指针发消息会报EXC_BAD_ACCESS错误

    3.空指针 没有指向存储空间的指针(里面存的是nil, 也就是0) 给空指针发消息是没有任何反应的

    4. 为了避免野指针错误的常见办法: 在对象被销毁之后, 将指向对象的指针变为空指针

    5.多对象内存管理

    问题:内存管理的原则?

    答:

    1.谁创建谁release

    如果你通过alloc、new、copy或mutableCopy来创建一个对象,那么你必须调用release或autorelease

    2.谁retain谁release:

    只要你调用了retain,就必须调用一次release

    3.总结:

    有加就有减,曾经让对象的计数器+1,就必须在最后让对象的计数器-1

    1.autorelease基本概念

    问题1:什么是自动释放池?

    答: autorelease是一种支持引用计数的内存管理方式,只要给对象发送一条autorelease消息,会将对象放到一个自动释放池中,当自动释放池被销毁时,会对池子里面的所有对象做一次release操作

    问题2:自动释放池的优点是什么?

    答:

    • 不用再关心对象释放的时间
    • 不用再关心什么时候调用release

    问题3:简述自动释放池的原理?

    答: autorelease实际上只是把对release的调用延迟了,对于每一个autorelease,系统只是把该 Object放入了当前的autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用release。

    问题4:如何使用自动释放池?(用代码书写)

    答:

    基本使用

    1)方法一:

    NSAutoreleasePool *autoreleasePool = [[NSAutoreleasePool alloc] init];

    Person *p = [[[Person alloc] init] autorelease];

    [autoreleasePool release];

    2)方法二:

    @autoreleasepool
    {
        // 创建一个自动释放池
        Person *p = [[[Person alloc]init] autorelease];
    } // 销毁自动释放池(会给池子中所有对象发送一条release消息)

    2.自动释放池注意事项

    问题1:自动释放池有哪些注意事项?

    答:

    1. 在自动释放池中创建了对象, 一定要调用autorelease,才会将对象放入自动释放池中
    2. 一个程序中可以创建N个自动释放池, 并且自动释放池还可以嵌套
    3. 不要再自动释放池中使用比较消耗内存的对象, 占用内存比较大的对象
    4. 尽量不要再自动释放池中使用循环, 特别是循环的次数非常多, 并且还非常占用内存
    5. 千万不要写多次autorelease
    6. 一个alloc/new对应一个autorelease或者release

    问题2:自动释放池是以什么形式存储的?

    答:

    • 如果存在多个自动释放池的时候, 自动释放池是以 "栈" 的形式存储在堆区
    • 栈的特点: 先进后出

    问题1:ARC的原理是什么?

    答: 当ARC开启时,编译器将自动在代码合适的地方插入retain, release和autorelease,而作为程序猿,完全不需要担心编译器会做错(除非开发者自己错用ARC了)。

    问题2:ARC有什么优点?

    答:

    1. 完全消除了手动管理内存的烦琐, 让程序猿更加专注于app的业务
    2. 基本上能够避免内存泄露
    3. 有时还能更加快速,因为编译器还可以执行某些优化

    问题3:ARC的原则是什么?什么是强指针?什么是弱指针?

    答: 只要还有一个强指针变量指向对象,对象就会保持在内存中

    1.强指针

    • 默认所有指针变量都是强指针
    • 被__strong修饰的指针
      例如:
      Person *p1 = [[Person alloc] init];
      __strong  Person *p2 = [[Person alloc] init];

    2.弱指针

    • 被__weak修饰的指针
    • __weak Person *p = [[Person alloc] init];

    4.ARC基本概念

    问题1:ARC下@property修饰符有哪些?

    答:

    • strong : 用于OC对象, 相当于MRC中的retain
    • weak : 用于OC对象, 相当于MRC中的assign
    • assign : 用于基本数据类型, 跟MRC中的assign一样

    问题2:ARC中是怎么对对象进行内存管理的?

    答:

    1.ARC下单对象内存管理

    1)ARC下,所有的指针都是强指针
    2)ARC, A对象想拥有B对象, 那么就需要用一个强指针指向B对象
    3)A对象不用B对象了, 什么都不需要做, 编译器会自动帮我们做

    2.ARC下多对象内存管理(strong ,weak, assign)

    // 在ARC中保存一个对象用strong, 相当于MRC中的retain
    @property(nonatomic, strong)Dog *dog;

    // 在ARC中如果保存对象不要用assign, 用weak
    // assign是专门用于保存基本数据类型的, 如果保存对象用weak
    @property(nonatomic, weak)Person *owner;

    问题3:ARC怎么解决循环引用问题?

    答:

    • ARC和MRC一样, 如果A拥有B, B也拥有A, 那么必须一方使用弱指针
    • 也就是说 一端用strong ,一端用weak

    6.ARM和MRC混编

    问题1:ARC模式下如何兼容非ARC的类?

    答:

    找到project->targets->Bulid Phases->Compiles Sources->找到相关文件右击右边Compiler Flags添加相关代码

    给相关文件添加一端代码,

    • 转变为非ARC -fno-objc-arc
    • 转变为ARC的, -f-objc-arc (不常用)

    7.MRC转ARC

    问题1:如何操作Xcode将MRC转ARC?

    答:Edit->Convert->To Objective ARC

     

  • 相关阅读:
    第10组 Beta冲刺(2/5)
    第10组 Beta冲刺(1/5)
    第10组 Alpha事后诸葛亮
    3月7-第十次机试课记录
    3月5-第九次机试课记录
    3月2-第八次机试课记录
    3月1-第六次机试课记录
    2月28-第五次机试课记录
    STL
    2月27-第四次机试课记录
  • 原文地址:https://www.cnblogs.com/dreamWanweidong/p/4997796.html
Copyright © 2011-2022 走看看