Iphone开发(6) 如何保证不出现内存泄露

Iphone开发(6) 如何保证不出现内存泄露,第1张

概述Objective-C已经有了垃圾回收机制,但是我们最关心的iso不支持垃圾回收,所以,让我们冷静一下,抛开垃圾回收,自己来管理内存吧。 对象所有权:当一个对象的属性是另外一个对象的时候,换言之,对象A中,有一个属性是对象B,那么,对象A对于对象B,就有对象所有权。那么,在对象A释放的时候,我们必须确保对象B的引用计数减少1(这里不一定是释放对象B,因为对象B还可能在其他地方被引用)。      

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) 如何保证不出现内存泄露所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1061986.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存