管理的范围:任何继承NSObject的对象,对其他的基本数据类型无效。
当代码快结束时,关于代码块中的所有局部变量会被回收,指向对象的指针也会被回收,此时对象
没有指针指向他看,但是依然存在于内存中,造成内存泄漏。
--------------------------------内存泄漏的分类--------------------------------
常发性:发生内存泄漏的代码会被多次执行到,每次被执行的时候都回导致一块内存泄漏。
偶发性:只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的,对于特定的环境,偶发性也就变成常发性了。
一次性:发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,总有一块内存发生泄漏。
隐式 :概括来说(内存会在程序结束以后释放,但是某些程序一开就是一个月,会造成内存泄漏的堆积,最终耗尽系统所以的内存)。
------------------------------对象的基本结构和引用计数------------------------
OC中每个对象都由自己的引用计数,是一个整数表示对象被引用的次数,就是想着有多少东西在使用这个对象,对象刚被创建时,默认计数器值为1,但计数器的值为0时,对象被销毁。
判断对象要不要回收的唯一依据就是计数器是否为0,若不为0则存在。
-------------------------------操作--------------------------------------
给对象发送消息,进行相应的计数器操作。
retain消息:使计数器+1,改方法返回对象本身
release消息:使计数器-1,(并不是代表释放对象本身)
retainCount:获得对象当前的引用计数器值
------------------------------------对象的销毁--------------------------------------------
当一个对象的引用计数为0时,那么这个对象被销毁,其占有的内存空间被回收。
*当对象被销毁时,系统会自动向对象发送一条dealloc消息,一般会重写dealloc方法,在这类释放相关的资源,dealloc就像是对象的遗言。一旦重写dealloc方法就必须调用【super dealloc】,并且放在代码块的最后调用(不能直接调用dealloc方法)。
注意:当对象被回收,其内存空间被回收,那么就不能通过指针再去访问这块内存空间(野指针)
-------------------------------僵尸对象----------------
僵尸对象:所占内存已经被回收的对象,僵尸对象不能再被使用。
空指针:没有指向任何东西的指针(存储的东西是0,null,nil),向空指针发送消息不会报错。
注意 不能使用[实例对象 retain]让见识对象起死回生。
内存管理的原则
1、原则
只要还有人在使用某一个对象,那么这个对象就不会被回收。
只要你想使用这个对象,那么久应该让这个对象的引用计数器+1。
当你不想使用这个对象时,应该让对象的引用计数器-1.
2、谁创建,谁release
(1)、如果你通过alloc、new、copy来创建一个对象,那么你就必须调用release或者autorelease
(2)、不是你创建的就不用你去负责。
3、谁retain,谁release
只要你调用了retain,无论这个对象是如何生成的,你都要调用release
4、总结
有始有终,有加有减,如果你让某一个对象计数器加1,就应该在其后面-1.
内存管理代码规范
-(void)setCar:(Car *)car
{
//1.先判断是不是新传进来的对象
If(car!=_car)
{
//2 对旧对象做一次release
[_car release];//若没有旧对象,则没有影响
//3.对新对象做一次retain
_car=[car retain];
}
}
dealloc方法的代码规范
(1)一定要[super dealloc],而且要放到最后
(2)对self(当前)所拥有的的其他对象做一次release操作
-(void)dealloc
{
[_car release];
[super dealloc];
}
Autorelease
1、基本用法:
a、会将对象放到一个自动释放池中
b、当自动释放池被销毁时,会对池子里的所有对象做一次release
c、会返回对象本身
d、调用完autrelease方法后,对象的计数器不受影响(销毁时影响)
2、好处
a、不需要在关系对象释放的时间
b、不需要再关系什么时候调用release
3、使用
a、占用内存较大的对象,不要随便shiyongautrelease,应该使用release来精确控制
b、占用内存较小的对象使用autrelease,没有太大的影响。
4、
多次使用autrelease
alloc之后调用了autrele,之后又调用了release
5、自动释放池
a、在iOS程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的
b、当一个对象调用autrele时,会将这个对象放到位于栈顶的释放池中
======================以下是上课后的添加=============================、
在手动管理模式中(MRC)中,便利构造器是内部执行了autorelease的 所以由变量构造器方法创建的实例对象是不用在使用完以后release。
加入容器的对象的引用计数会执行一次retain操作,引用计数加一。
在对象被容易删除是,对象会执行一次release操作,引用计数减一。
当容器被销魂时,容器会对所有对象执行一次release操作,所以对象引用计数减一。
当对象执行一次setter方法时,由于setter内部执行了一次retain操作 ,所以必须在最后对象销毁时,对对象所以的实例变量执行一次release操作
-(void)setName:(NSString*)name{
if (_name != name) {
[_name release];
_name = [name retain];
}
}
-(NSString*)name{
return [[_name retain]autorelease];
}
- (void)dealloc {//属性的setter方法造成的实例变量的内存泄漏,全部放到dealloc方法内部执行release操作。
NSLog(@"%@的对象被释放了",self);
[_name release];
[_gender release];
[_mArr release];
[super dealloc];
}