iphone 会对程序占用内存设置阀值,当达到第一和第二阀值的时候,会进行警告,如果已经达到第三阀值时,则OS会直接kill.
内存管理的目的:就是将不参与逻辑的对象,清除出内存,把空间给需要参加逻辑的对象
1.严格的内存管理让程序的性能得到提高
2.如果忽视内存管理,将导致程序占用内存过高,进而导致程序崩溃
注意:2012年的之前的项目很多都是手动内存管理,没有ARC,IOS5后都是ARC机制。
如果是Xcode4.0以上的版本,Xcode以上的版本模式内存管理是ARC,手动内存需要对编译器做以下设置 :
工程目录--> Buid Settings --> Objective-C Automatic Reference Count --> 修改为NO。
在对象中,有个retainCount属性,是该对象的引用计数器值,如果等于0,则表示对象已经没有引用,就会调用dealloc方法进行摧毁死亡。对象的属性和方法将不能被调用。但可以人为的干预retainCount的值。
1) 使用alloc、new或者copy创建一个新对象时,新对象的引用计数器默认为1
2) 调用对象retain方法,会让引用计数器值+1(retain方法id指针)
3) 调用对象release方法,会让引用计数器值-1
4) 通过对象retainCount方法,获得当前的引用计数器值
5) 当retainCount=0时,对象就认为要摧毁,会自动调用dealloc 函数通知对象即将死亡。及时性。
只要出现了new alloc retain 就必须配对出现严格release 或者 autorelease; 如果没有按照这种规则来写,则会有内存泄露的风险。
1) 谁创建,谁release
如果你通过alloc、new或[mutable]copy来创建一个对象,那么你必须调用release或autorelease
2) 谁retain,谁release
只要你调用了retain,无论这个对象是如何生成的,你都要调用release
内存溢出:对象使用完毕,但是并没有移除内存。retainCount 不为0
野指针:指向释放掉的对象的指针,为了防止野指针,将使用完毕的对象赋值为nil
僵尸对象:retainCount 为0 的就是僵尸对象,代表不能正确访问的对象
EXC_BAD_ ACCESS DA 代表访问了一块被释放掉的内存,野指针
Car Engine类,Car类是Engine类的父类,他们具有组合关系,Car拥有Engine
1.Car类
===Car类声明=== @interface Car : NSObject @property (nonatomic,strong)Engine *engine; -(void)setEngine:(Engine *)engine; @end ===Car类实现=== @implementation Car - (void)dealloc { [_engine release]; NSLog(@"%@ dealloc...",self.className); [super dealloc]; } //重写set方法 -(void)setEngine:(Engine *)engine { //第一次重写 /* 重写代码: _engine=engine; 调用代码分析 Car *car = [[Car alloc]init]; Engine *engine = [[Engine alloc]initWithMode:@"byd"]; [car setEngine:engine]; 该步骤是Car的 _engine 成员变量指向 engine对象,也就是引用数+1。 但是setEngine 方法中的 _engine=engine 并未让retainCount+1. [engine release];//这步 engine 释放。 [car release]; */ //第二次改进 /* 重写代码: _engine=[engine retain]; 调用代码分析: Car *car = [[Car alloc]init]; Engine *engine1 = [[Engine alloc]initWithMode:@"byd"]; [car setEngine:engine1];//设置的时候,又有另外一个指针指向engine NSLog(@"engine1=%p",engine1); //更换引擎 Engine *engine2 = [[Engine alloc]initWithMode:@"byd"]; [car setEngine:engine2];//_engine 指向 engine2 NSLog(@"engine2=%p",engine2); [engine1 release]; [engine2 release]; [car release]; 输出结果 014-10-22 23:16:16.613 08-内存管理1[1586:303] engine1=0x1001034c0 2014-10-22 23:16:16.615 08-内存管理1[1586:303] engine2=0x10010cf30 2014-10-22 23:16:16.615 08-内存管理1[1586:303] 0x10010cf30 dealloc... 2014-10-22 23:16:16.615 08-内存管理1[1586:303] Car dealloc... 可以看出engine1并没有被释放,照成了内存溢出。并且程序也不符合原理,在engine2赋值给car时,engine1引用值-1; */ //第三次改进 /* 改进后的代码: [_engine release]; _engine=[engine retain]; 该代码已经解决了上面的问题。 代码分析: Car *car = [[Car alloc]init]; Engine *engine1 = [[Engine alloc]initWithMode:@"byd"]; [car setEngine:engine1];//这步_engine = engine1; engine1 的 retainCount=2; NSLog(@"engine1=%p",engine1); //更换引擎 Engine *engine2 = [[Engine alloc]initWithMode:@"byd"]; [car setEngine:engine2];//这步 先让engine1 引用数-1,让后把engine2的引用数+1,并且赋给_engine NSLog(@"engine2=%p",engine2); [engine1 release];//engine1被摧毁 [engine2 release];//这步 engine2 retainCount= 1 [car release];//cat 被摧毁 调用dealloc方法,摧毁 engine2 和 car对象 输出: 2014-10-22 23:24:46.037 08-内存管理1[1605:303] engine1=0x1002005c0 2014-10-22 23:24:46.039 08-内存管理1[1605:303] engine2=0x100403840 2014-10-22 23:24:46.039 08-内存管理1[1605:303] 0x1002005c0 dealloc... 2014-10-22 23:24:46.039 08-内存管理1[1605:303] 0x100403840 dealloc... 2014-10-22 23:24:46.040 08-内存管理1[1605:303] Car dealloc... */ //最终代码 if (_engine != engine) {//避免重复调用,如果重复调用,先把引用数-1,再+1,没有意义 [_engine release]; _engine=[engine retain]; } } @end
2.Engine类
===类声明=== @interface Engine : NSObject @property (nonatomic,copy)NSString *mode; - (instancetype)initWithMode:(NSString *) mode; @end ===类实现=== @implementation Engine - (void)dealloc { NSLog(@"%p dealloc...",self); [super dealloc]; } - (instancetype)initWithMode:(NSString *) mode { self = [super init]; if (self) { [self setMode:mode]; } return self; } @end
3.主函数
int main(int argc, const char * argv[]) { Car *car = [[Car alloc]init]; Engine *engine1 = [[Engine alloc]initWithMode:@"byd"]; [car setEngine:engine1];//设置的时候,又有另外一个指针指向engine NSLog(@"engine1=%p",engine1); //更换引擎 Engine *engine2 = [[Engine alloc]initWithMode:@"byd"]; [car setEngine:engine2];//_engine 指向 engine2 NSLog(@"engine2=%p",engine2); [engine1 release]; [engine2 release]; [car release]; return 0; } 输出 2014-10-23 00:12:34.840 08-内存管理1[1812:303] engine1=0x1002005c0 2014-10-23 00:12:34.841 08-内存管理1[1812:303] engine2=0x100100370 2014-10-23 00:12:34.841 08-内存管理1[1812:303] 0x1002005c0 dealloc... 2014-10-23 00:12:34.842 08-内存管理1[1812:303] 0x100100370 dealloc... 2014-10-23 00:12:34.842 08-内存管理1[1812:303] Car dealloc...