Objective-C已经有了垃圾回收机制,但是我们最关心的iso不支持垃圾回收,所以,让我们冷静一下,抛开垃圾回收,自己来管理内存吧。
对象所有权:当一个对象的属性是另外一个对象的时候,换言之,对象A中,有一个属性是对象B,那么,对象A对于对象B,就有对象所有权。那么,在对象A释放的时候,我们必须确保对象B的引用计数减少1(这里不一定是释放对象B,因为对象B还可能在其他地方被引用)。
一个非常常见的例子就是set方法,把一个对象设置为另外一个对象的属性。在这里,我们必须确保引用计数不混乱,一个良好的实现如下:
//这里还没有解决Car释放的时候,Engine跟着释放-(voID) setEngine:(Engine *) newEngine{ [newEngine retain];//增加newEngine的引用计数,标示着Car对newEngine的对象所有权 [engine release];//释放旧的engine engine = newEngine;//引用新的newEngine}
自动释放池:一个容器,可以装载对象,当池销毁的时候,同时给每一个对象发送release消息(注意这里是发送release消息,而不是直接销毁里面的对象)。当给一个对象发送autorelease消息时,实际上是将该对象添加到NSautorelease中。当自动释放池被销毁时,会给该对象发送release消息。当然,自动释放池也是一个正常的Objective-C对象,它也遵守引用计数规则。下面有两个例子,可以比较清晰的展示自动释放池的工作现象。
#import <Foundation/Foundation.h>@interface RetainTracker : NSObject@end @implementation RetainTracker- (ID) init{ if (self = [super init]) { NSLog (@"init: Retain count of %d.",[self retainCount]); } return (self); } - (voID) dealloc{ NSLog (@"dealloc called. Bye Bye."); [super dealloc]; } @endint main (int argc,const char * argv[]){ NSautoreleasePool *pool; pool = [[NSautoreleasePool alloc] init]; RetainTracker *tracker; tracker = [RetainTracker new]; // count: 1 [tracker retain]; // count: 2 //把tracker加入到自动释放池中 [tracker autorelease]; // count: still 2 [tracker release]; // count: 1 NSLog (@"releasing pool"); [pool release]; return (0);}
#import <Foundation/Foundation.h>@interface RetainTracker : NSObject@end @implementation RetainTracker- (ID) init{ if (self = [super init]) { NSLog (@"init: Retain count of %d.",const char * argv[]){ NSautoreleasePool *pool; pool = [[NSautoreleasePool alloc] init]; RetainTracker *tracker; tracker = [RetainTracker new]; // count: 1 [tracker retain]; // count: 2 [tracker retain]; // count: 3 //把tracker加入到自动释放池中 [tracker autorelease]; // count: still 3 [tracker release]; // count: 2 NSLog (@"releasing pool"); [pool release]; return (0);}
请读者自行比较两段代码的输出。
Cocoa内存管理规则:
1.当你使用new、alloc、copy方法创建一个对象时,该对象的保留计数器值为1。当不再使用该对象的时候,你要负责向该对象发送一条release或autorelease消息。这样,该对象将在其使用寿命结束时被摧毁。
2.当你通过任何其他方法获得一个对象时,你不需要执行任何 *** 作来确保该对象被清理。就比如这样的语句:NSMutableArray *array = [NSMuableArray arrayWithCapacity:17];你不需要维护array的引用计数,系统会帮你完成(借助于自动释放池)。当然,如果你打算在一段时间内拥有array,你需要给它增加引用计数,并且在不使用的时候减少引用计数。
3.如果你保留了某个对象,你需要释放或者自动释放该对象。必须保持retain方法和release方法的使用次数相等(就必须开始讨论的set方法)。
最后说明两个问题:
1.开始的set方法并没有确保对象销毁时,它的属性对象也销毁,处理的方式很简单,在对象的dealloc方法中,给属性对象发送release。
2.自动释放池也不是可以乱用的,比如在循环中,我们不断的新建对象,而且对象被加载到自动释放池中。那么,当循环很大的时候,被加载到自动释放池的对象并没有被释放,我们的程序占用的内存会持续增长。这时候的处理方法是不断的创建自己的自动释放池,然后释放(释放的时候,里面的对象也跟着释放了),再创建,再释放。
总结以上是内存溢出为你收集整理的Iphone开发(6) 如何保证不出现内存泄露全部内容,希望文章能够帮你解决Iphone开发(6) 如何保证不出现内存泄露所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)