内存问题
管理内存的三种方式
引用计数机制:
iOS采用计数器来管理内存,当你拥有这个对象的时候,需要使用该对象的引用计数+1,当对象的引用计数器为0的时候,表示没有任何对象对该对象持有,那么这个时候系统会
自动调用dealloc方法来回收对象的存储空间
影响引用计数器的方法
使引用计数器+1的方法: alloc, retain, copy
使引用计数器-1的方法:release, autoreleae
retainCount 是ARC才有的机制所以要将MRC转换ARC
如图所示:将ARC模式关闭
1.release 使用引用计数减一
1 Person *person = [[Person alloc]init]; 2 NSLog(@"retainCount = %lu",person.retainCount); 3 [person release]; 4 NSLog(@"retainCount = %lu",person.retainCount);
2. retain使引用计数加一
1 Person *person = [[Person alloc]init]; 2 NSLog(@"retainCount = %lu",person.retainCount); 3 [person retain]; 4 NSLog(@"retainCount = %lu",person.retainCount);
3.野指针和僵尸对象
1 Person *person = [[Person alloc]init]; 2 NSLog(@"retainCount = %lu",person.retainCount); 3 [person release]; // 1 4 NSLog(@"%lu",person.retainCount); // 1 5 6 [person release]; //0 当对象的引用计数为0,系统自动调用dealloc方法 7 8 person = nil; // 对象置为nil,防止野指针异常 // 僵尸对象指的是:对象的引用计数器变成0后,该块地址被回收,变成不可访问的内存。 // 野指针指的是:指向僵尸对象(不可用内存)的指针,给野指针发送消息会报错(EXC_BAD_ACCESS) // 空指针:没有指向任何东西的指针(存储的东西是nil、NULL、0),给空指针发送消息不会报错
4.开启 zombie 检测
5. 自动释放池
// 定义一个自动释放池 // 第一种形式 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // pool 1 Person *p1 = [[Person alloc] init]; NSLog(@"%lu", p1.retainCount); [p1 retain]; // 2 [p1 autorelease]; NSLog(@"p1 = %lu", p1.retainCount); NSLog(@"pool = %lu", pool.retainCount); [pool release];
NSLog(@"p1 = %lu", p1.retainCount); // 1
// 对象使用 autorelease是在未来的某一时刻让对象的引用计数器减一,这个某一时刻是指碰到自动释放池子之后才会释放
// iOS 5.0 之后推荐使用的 // 第二种形式 @autoreleasepool { Person *p2 = [[Person alloc]init]; // [p2 retain]; p2.name = @"p2"; [p2 autorelease]; NSLog(@"p2 = %lu", p2.retainCount); Person *p3 = [[Person alloc]init]; // [p2 retain]; p3.name = @"p3"; [p3 autorelease]; NSLog(@"%lu", p3.retainCount); }
// 总结:自动释放池的作用:自动释放池会在销毁的时候检查内部有没有autorelease对象,如果有autorelease对象,让该对象的引用计数做一次减一操作(即让池子内所有的引用对象减一)
// 销毁方式 以栈的形式销毁的
6. 内存管理原则
// 凡是使用alloc, retain让对象的引用计数加一,相应的就该使用release或者autorelease让对象的引用计数减一,业绩也是说增加的次数要和减少的次数相等,才能保障对象的引用计数始终唯0,对象才可以被销毁
// 不想等的情况下,会出现
// 1. 内存泄露:增加的次数大于减少的次数
// 情况一
Person *person1 = [[Person alloc]init];
// 情况二
Person *person2 = [[Person alloc]init];
[person2 retain]; // 2
[person2 release]; // 1
// 情况三
Person *person3 = [[Person alloc]init];
person3 = nil;
[person3 release];
// 2.过度释放:增加的次数小于减少的次数
Person *person1 = [[Person alloc]init]; // 1
[person1 retain]; // 2
[person1 release]; // 1
[person1 release]; // 0
[person1 release]; // 过度释放
// 3.野指针异常: 增加的次数等于减少的次数,还继续访问
Person *person =[[Person alloc]init];
[person retain];
[person release];
[person release];
person = nil;
NSLog(@"person = %lu",person.retainCount);
原文:http://www.cnblogs.com/hybl/p/5331688.html