内存管理(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

 

原文地址:https://www.cnblogs.com/dreamWanweidong/p/4997796.html