OC的内存管理,MRC与ARC以及一些常见名称概念

OC的内存管理以及MRC与ARC

内存中的五大区域:

栈区,堆区,BBS段,数据段和代码段,其中除了堆区以外,其他区域的内存管理由系统自行回收

OC对象是存储在堆区的,所以OC的内存管理主要是对”堆区中的OC对象”进行管理

内存管理中的几个概念:

->引用计算器:既retainCount,每个OC对象内部都有1个8字节空间用来存储retainCount,表示有多少”人”正在使用;

对象刚被创建时,默认计数值就为1,当计数值为0时,系统会自动调用dealloc方法将对象销毁

引用计数器的用法:给对象发送相应的技术操作来改变计数器的值

retain消息:使计数器+1

release消息:使计数器-1

retainCount消息:得到当前当前retainCount的值

->野指针:没有初始化的指针变量

->僵尸对象:指一个对象已经被回收,但其数据还存在内存中

僵尸对象有可能可以访问,也有可能不能访问,取决于所占用空间是否已被重新分配.然而,对象一旦被回收就不该再被访问,此时可以开启僵尸对象检测,这样系统会自动检查是否为僵尸对象,但同时也会降低执行效率.

->内存泄露:指对象没有在该回收的时候被回收,而是一直驻留在内存中,直到程序结束的时候才被释放

内存管理的分类:

->MRC:Manual Reference Counting,既手动内存管理

对引用计数器的操作全由程序员亲自完成

->ARC:Automatic Reference Counting,既自动内存管理

(垃圾回收不能在iOS系统使用,故此处暂不讨论)

系统会依照程序员的要求自动改变引用计数器的值(Xcode6开始,默认使用ARC)

手动内存管理:

->手动内存管理的原则:

1)一旦创建一个对象,这个对象的引用计数器的值就为1,所以必须要匹配1个release

2)只有在多1个人使用这个对象的时候才retain

只有在烧1个人使用这个对象的时候才release

3)retain的次数要和release次数相匹配

4)永远不要手动调用对象的dealloc方法,而是让系统自动调用

->手动内存管理中内存泄露的几种情况:

1) retain和release不匹配,retain多余release导致的内存泄露;

2) 对象使用过程中,没有被release,而被赋值为nil;

3) 在方法中不当的使用了retain;

手动内存管理的关键就是防止内存泄露!!!!!防止内存泄露要记住:

1) 谁创建”alloc","new",谁"release";

2) 谁”retain",谁"release";

->多对象的手动内存管理:

当B类作为A类属性时,要防止内存泄露,则A类的setter方法应为:

其中setter方法实现还可写成:

以上是标准的MRC内存管理代码.

->循环retain问题:

1) 遇到的问题:

当两个对象相互引用的时候.

A对象的属性指向B对象, B对象的属性指向A对象.

这个时候,如果两边都使用retain.就会出现内存泄露. 都回收不了.

2) 解决方案:

1端使用retain,1端使用assign.(请查看@property带参数用法的相关内容)

需要注意的是: 使用assign的那1段,dealloc中不需要再去release这个对象了.

->自动释放池(autorelease)

1)原理:

存储在自动释放池的对象,在自动释放池销毁时,会自动调用该对象的release方法,故将对象存储在自动释放池中,就不需要再写release

2)创建方法:

@autorelease

{

} //大括弧表示自动释放池的范围

3)将对象放入的方法:

在自动释放池的范围中调用对象的autorelease方法.注:autorelease的返回值是对象本身,所以我们可以这样创建对象:

@autorelease

{

类型 *对象 = [类名 alloc] init] autorelease];

}

4)使用注意:

a.只有在自动释放池中调用了对象的autorelease方法,这个对象才会被存储到这个自动释放池之中

b. 对象的创建可以在自动释放池的外面,在自动释放池之中,调用对象的autorelease方法,就可以将这个对象存储到这个自动释放池之中.

c. 当自动释放池结束的时候.仅仅是对存储在自动释放池中的对象发送1条release消息 而不是销毁对象.

d. 如果在自动释放池中,调用同1个对象的autorelease方法多次.就会将对象存储多次到自动释放池之中.在自动释放池结束的时候.会为对象发送多条release消息.那么这个时候就会出现僵尸对象错误.

e. 自动释放池可以嵌套.调用对象的autorelease方法,会讲对象加入到当前自动释放池之中,只有在当前自动释放池结束的时候才会像对象发送release消息.

5)使用规范:

我们一般情况下,写1个类.会为我们的类写1个同名的类方法,用来让外界调用类方法来快速的得到1个对象.应遵守规范:使用类方法创建的对象,要求这个对象在方法中就已经被autorelease过了.这样,我们只要在自动释放池中, 调用类方法来创建对象, 那么创建的对象就会被自动的加入到自动释放中.

自动内存管理:

->自动内存管理原则: 编译器会自动的在合适的地方插入retain、release、autorelase代码;编译器自动为对象做引用计数. 而作为开发者,完全不需要担心编译器会做错(除非开发者自己错用了ARC).

->强指针与弱指针:

强指针:默认情况下,我们声明的指针都为强指针,也可以使用__strong来显示的声明指针为强指针.

弱指针:使用__weak关键字修饰的指针,例如 __weak Person *p;

作用与区别:在ARC模式下,强指针与弱指针用来作为回收对象的标准,当1个对象即使用弱指针指向,但没有任何强指针指向时就会被立即回收,此时该弱指针会被自动设置为nil.

->ARC模式下的循环引用:

在ARC机制下,如果出现了循环引用,既A对象中有1个属性是B对象. B对象中有1个属性是A对象.此时如果两边都为strong.就会发生内存泄露.

解决方案:1端使用strong 另外1端使用weak

MRC和ARC的转换与兼容:

#  ARC兼容MRC的类

target --> Build Phaese  --->  Compiler Sources --> Compiler Flags

让程序兼容ARC和非ARC部分。

转变为非ARC  -fno-objc-arc

转变为ARC的, -f-objc-arc

#  MRC转ARC

Xcode —> refactor  -->  Convert to Objective-C ARC  选中要装换的target -->  调校代码

你可能感兴趣的