内存管理详解

来谈谈内存管理

首先知道内存管理是什么
应用程序内存管理是在程序运行的时候合理的分配内存(分配内存时不会造成内存泄露等)与清除内存(销毁一个不用的程序,减少内存使用)

为什么要进行内存管理呢
苹果手机的内存大多都是1G,分配给每个App程序的内存空间有限制,当程序运行时,所占用的内存较大时,就会收到系统给的内存警告,如果超过所占用内存超过限制是,会被系统强制关闭的,所以我们需要对应用程序进行内存管理,一个好的App程序会尽可能的减少占用内存

在OC中有两个管理内存的模式
MRR(Manual Retain-Release),也被人称作MRC(Manual Reference Counting,手动引用计数)
ARC(Automatic Reference Counting,自动引用计数)

如何调整
在Build Setting中的Objective-C Automatic Reference Counting设置为YES即为ARC

注意点,所有继承NSObject的对象都需要管理内存,因为存放在堆里面,基本数据类型不需要管理内存,因为放在栈里面

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

在iOS5以前,程序都需要手动添加retain,release,atorelease来管理对象的内存

当使用alloc、new、copy、mutableCopy创建一个新对象时,该新对象的引用计数器为1
当给对象发送一条retain消息时,对象的引用计数器+1(方法返回对象本身)
当给对象发送一条release消息时对象的引用计数器-1(方法无返回值)
当给对象发送一条retainCount消息时,返回对象的当前引用计数器(不要以该数据来判断对象是否被释放)

注意点:
对对象发送一个release消息,不代表对象会释放,只有对象的引用计数器为0时才会被释放

在内存管理中,会产生将是对象,野指针,空指针
僵尸对象: 所占用的内存已经被回收的对象,僵尸对象不能再使用
野指针: 指向僵尸对象的指针,给野指针发送消息会报错EXC_BAD_ACCESS错误:访问了一块已经被回收的内存
空指针: 没有指向任何对象的指针(存储的东西是nil,NULL,0),给空指针发送消息不会报错,系统什么也不会做,所以在对象被释放时将指针设置为nil可以避免野指针错误

僵尸对象,Xcode是不会主动监听的,需要我们自己去打开
步骤很简单,
对象步骤为: Edit Scheme ->; Run ->; Diagnostics ->; Objective-C的Enable Zombie Objects打钩

Dog *D = [[Dog alloc] init]; // 引用计数器 = 1
[D release]; // 引用计数器 - 1 = 0,指针所指向的对象的内存被释放
[p release]; // 这句给野指针发送消息,会报野指针错误,开启监听僵尸对象会给出错误信息**- -[Person release]: message sent to deallocated instance 0x100206fd0

自动释放池的概括
自动释放池提供了延迟放弃一个对象的所有权的机制,比如想要在一个方法中返回一个对象,如果先使用release放弃了该对象的所有权,那么return返回的对象便是一个僵尸对象,如果先进行return返回,那么便无法放弃该对象的所有权,导致了内存泄漏

autorelease是一种支持引用计数的内存管理方式,只要在自动释放池中给对象发送一条autorelease消息,就会将对象放到自动释放池中,当自动释放池被销毁时,会对池中的所有对象发送一条release消息

autorelease方法会返回对象本身
autorelease方法不会修改对象的引用计数器
autorelease方法可以让开发者不用实时关心什么时候发送release消息

类工厂方法内存管理
在开发中,我们经常使用Foundation框架中的类,在调用其类工厂方法创建一个对象时,因为并不是使用alloc,new,copy或者mutableCopy方法创建的,所以并不需要我们自己在给该对象发送release或者autorelease消息,这是因为类工厂方法内部都已经在返回对象前进行过延迟释放

我们在自己书写类工厂方法时,也应该与系统处理方式相同,快速返回一个autorelease对象的方式具体如下
+ (instancetype)person
{
// 使用self而不是使用Person是因为这样可以在子类调用该方法时会返回子类的对象
return [[[self alloc] init] autorelease];
}

快速返回一个带有参数的autorelease对象的方式具体如下
+ (instancetype)personWithName:(NSString *)name
{
Person *person = [[[self alloc] init] autorelease];
person.name = name;
return person;
}

ARC的概括
ARC是iOS4引入的一项新技术(从iOS5开始支持弱引用),其使用与MRR&MRC相同的内存管理规则来管理内存,不过编译器会在编译阶段自动的插入retain、release和autorelease等内存管理代码来管理内存不再需要程序人员手动管理.非常方便,所以现在用的都是ARC模式

多人开发时需要注意的
1> 使用Analyze进行代码的静态分析
2> 为避免不必要的麻烦, 多人开发时尽量使用ARC

和MRC相比消除了手动管理内存的烦恼,不需要手动调用retain,release和aytorelease等方法来管理内存
编译器还会在适当的位置上插入代码

在ARC和MRC的属性修饰符

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

在什么情况下会发生内存泄露
1> 当程序在申请内存后,无法释放已申请的内存空间(例如一个对象或者变 量使用完成后没有释放,这个对象一直占用着内存),一次内存泄露危害 可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

2> 内存泄露会最终会导致内存溢出! 当程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个int,但给它存了long才能存下的数,那就是内存溢出。

iOS内存管理之Copy
概述
copy(复制、拷贝)是产生一个副本对象的过程,只要是通过拷贝产生的副本对象,副本对象中的内容与源对象中的内容就完全一致,下面介绍几个copy相关的知识点

copy的特点
修改源对象的属性和行为,不会影响副本对象
修改副本对象的属性和行为,不会影响源对象
copy与mutableCopy
使用copy产生的副本对象是不可变的(如NSString,NSArray)
使用mutableCopy产生的副本对象是可变的(如NSMutableString,NSMutableArray)
通过拷贝是否会产生新的对象
通过拷贝是否会产生新对象,就要看源对象与副本对象是否满足拷贝的特点

可变对象通过mutableCopy,会生成新的对象
可变对象通过copy,会生成新的对象
不可变对象通过mutableCopy,会生成新的对象
不可变对象通过copy,不会生成新的对象(因为源对象与副本对象都是不可变的,已经满足拷贝的特点)
深拷贝(内容拷贝)与浅拷贝(指针拷贝)
深拷贝: 如果通过拷贝生成了新对象,就称为深拷贝(内容拷贝)
浅拷贝: 如果通过拷贝没生成新对象,就称为浅拷贝(指针拷贝)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值