iOS*内存管理

概述

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

OC对象是存储在堆区的,所以OC的内存管理主要是对”堆区中的OC对象“进行管理。如果一个对象创建并使用后没有得到及时释放那么就会占用大量内存。其他高级语言如C#、Java都是通过垃圾回收(GC)来解决这个问题,但是OC没有垃圾回收机制,因此他的内存需要手动维护。

OC的内存管理中,其实就是引用计数的管理。

Xcode4.2之后引入ARC(Automatic Reference Counting)机制,Xcode可以自动添加内存释放代码,默认不需要手动维护内存。如果需要关闭ARC:项目属性->Build Settings->搜索“garbage”找到“Objective-C Automatic Reference Counting”设置为NO即可。

ARC项目单独设置某一文件为非ARC:项目属性->Build Phases->Compile Sources->找到对应文件.m 添加“-fno-objc-arc”

非ARC项目,单独设置某一文件为ARC:项目属性->Build Phases->Compile Sources->找到对应文件.m 添加“-fobjc-arc”

引用计数器(retainCount)

引用计数器是记录一个对象被引用次数的机制,通过引用计数值来判断是否释放对象回收内存,为0时释放对象。

当通过new、alloc、copy方法创建一个对象时,该对象的引用计数为1;

给对象发送retain消息,引用计数+1;

给对象发送release消息,引用计数-1;

dealloc当实例对象被销毁之前,系统自动调用,一定要掉[super dealloc],同时对该类的所有对象做释放;

在OC中当对象没有被任何变量引用(没有指针指向该对象)时,会被释放(对象占用的内存被回收利用)。

OC采用引用计数的技术来管理对象是否释放。每个对象都有一个关联的整数,称为引用计数器,当引用计数归0时,对象将被释放。

管理规则

黄金法则:谁创建(retain,new),谁释放(release)

如果要持有某一对象,就必须做一次retain操作,引用计数+1。
如果要放弃对某个对象的持有权,就要做一次release操作,引用计数-1。

MRC

手动引用管理,实在我们申请到某一块内存,在使用之后要手动释放,释放机理设计引用计数问题,如果未释放内存,或造成内存泄露,甚至引起很多未知的错误。
1、通过new、alloc、copy创建一个对象时,引用计数为1,当不再使用该对象时,应该通过release/autorelease释放对象
2、获取对象的所有权后,该对象的引用计数+1,需要保留对象并在操作完成之后释放,必须保证retain和release次数对等
3、通过其他方法获取一个对象,如果对象引用计数为1且被设置为autorelease,不需要执行任何释放对象的操作。

ARC

MRC时代必须遵守以上规则,但ARC之后,不需要再写无止境的retain和release,关于内存的申请、使用和释放过程都交给系统自动实现,实际上,ARC不是垃圾回收,也并不是不需要内存管理了,他是隐式的内存管理,编译器在编译的时候会在代码插入合适的retain和release语句,相当于在背后帮我们完成了内存管理的工作,实际上还是mrc原理。

iOS5(Xcode4.2)之后可以开启ARC模式,可以帮我们想对象发送retain/release消息,不需要手动添加,可以更舒心的创建或引用对象,简化内存管理步骤。

MRC和ARC的优缺点

ARC的缺陷:ARC能帮我们简化内存管理问题,但也有他不能处理的情况。这就需要手动处理,比如循环引用、非OC对象、Core Foundation中的malloc()或者free()等。

目前应用开发ARC是大趋势,自动帮我们完成许多以前需要手动完成的工作,只是需要对一些特殊情况作特殊对待即可。

循环引用

问题:当两个对象互相引用,A对象的属性指向B对象,B对象的属性指向A对象,这个时候两边都是用retain的话,就会出现内存泄露,都回收不了。

解决方案:A和B一个属性使用retain,一个使用assign

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

自动释放池autorelease

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

创建方法:

'@autorelease{
类型*对象 = [[[类名 alloc] init] autorelease];}
'

在自动释放池中调用对象的autorelease方法,autorelease的返回值是对象本身。

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

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

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

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

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

内存管理相关名词

1、僵尸对象:此对象被销毁,不能再使用,不能给他发送任何消息

2、野指针:指向僵尸对象(不可使用的内存)的指针,给野指针发送消息将会发生不可控的后果。

3、空指针:没有指向任何对象的指针,给空指针发消息不会发生任何行为

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

最新更新文章

猜你喜欢

转载自blog.csdn.net/fengzhixinfei/article/details/71480386