在Objective C中释放内存的最佳方法是什么?

时间:2010-02-04 06:17:18

标签: iphone objective-c xcode memory-management nsstring

我对内存管理有疑问。

让我们从一个例子开始。假设我们有一个类如下。

@interface myClass : NSObject {
    NSString *xyz;
}
@end

现在,请参阅实施。

@interface myClass : NSObject {
    NSString *xyz;
}
@end

@implementation myClass
-(void)abc{
    // xyz allocted here
}
-(void)pqr{
    // retained or copied many times or may not a single time
}
-(void)mno{
    // retained or copied many times or may not a single time
}
-(void)jpg{
    // may be released more than one time or may be not
}


//-(void)dealloc{
//  [xyz release];
//  [super dealloc];
//}
//
//-(void)dealloc{
//  if(xyz!=nil && [xyz retainCount]>0){ [xyz release]; xyz=nil; }
//  [super dealloc];
//}

-(void)dealloc{
    if(xyz!=nil){ 
        while([xyz retainCount]>0) 
           [xyz release]; 
        xyz=nil; 
    }
    [super dealloc];
}
@end

在上面的代码中。我有三个dealloc函数。哪个更好?如果没有,请建议你的。

我很困惑,因为Objective C说,每次都必须释放对象=每次分配/保留。

但是大多数示例代码只有一个语句“[xyz release];”它不会造成内存泄漏吗?

5 个答案:

答案 0 :(得分:12)

这是绝对错误的:

while([xyz retainCount]>0) 
       [xyz release]; 
    xyz=nil; 

retainCount将永远不会返回0,因为只要您处于retainCount为1且对象被释放,运行时就会立即释放它,然后永远不会减少retainCount 。即使它确实减少了retainCount,该对象现在也被释放了。你怎么会问它什么是retainCount?

简而言之,您的设计是错误的。如果你无法跟踪你以更聪明的方式保留对象的频率,那么你将有内存泄漏并且很可能会因过度释放的对象而崩溃(这会导致你的应用程序崩溃)

如果你绝对无法改变你的代码(如果你说你不能改变我就不相信你),那么你想要保留第二个整数ivar,表明你保留了多少次{{1然后使用 来确定应该释放它的次数。 (但是,这应该是一个绝对的最后努力,因为如果你没有在30秒内完成这项工作,就会发生Armaggeddon。你应该首先重构你的代码。)

此外,您忘记了xyz方法中对[super dealloc]的来电。

答案 1 :(得分:4)

- (void)dealloc {
    [xyz release];
    [super dealloc];
}

...是正确的版本。在Objective-C中,通常不应使用retainCount方法。

如果你想要非常安全,你也可以写:

- (void)dealloc {
    [xyz release], xyz = nil;
    [super dealloc];
}

答案 2 :(得分:1)

我的想法是myClass有一个成员变量(在你的例子中是xyz)。当创建myClass对象时,它应该通过仅向保留计数添加1来创建(或获取对xyz的引用)(无论是通过保留还是其他方式取决于具体情况)。

在每种方法中保留xyz并再次释放它并不是一个好主意。因此,在每个方法结束时,本地对象应该不再拥有xyz,而不是在方法开头时。

当dealloc被调用时,只有那个单独的retain hold应该保留在xyz上(就myClass对象而言),所以单次调用release就足够了。在retainCount为零之前发布并不是一个好主意,因为某个地方的某个对象可能正在使用它。

要直接回答您的问题,请使用此dealloc:

-(void)dealloc{
    [xyz release];
}

答案 3 :(得分:1)

在poperty声明中保留的对象需要在dealloc方法中释放。所以如果你宣布

@property(nonatomic, retain)NSString xyz;

你需要以dealloc发布

-(void)dealloc{
    [xyz release];
    [super dealloc]
}

在方法中最后一次使用该对象后,应立即释放任何其他已分配的内存。

所以如果你在

中分配xyz
-(void)abc{
    // xyz allocted here
}

然后你会在同一方法结束时释放它。

-(void)abc{
    // xyz allocted here
// do something with xyz

//release xyz

示例:

        -(void)abc{
           xyz=[[NSString alloc]init];//this may not be what you are following, but i just meant allocating memory
        // do something with xyz


    [xyz release]  

  //release xyz

在这种情况下,您无需在dealloc方法中释放它。

同样不是如果你是声明xyz并对其进行修饰的属性,你不应该在你的方法中分配它,也不应该发布

答案 4 :(得分:0)

    while([xyz retainCount]==0) 
       [xyz release]; 

应为> 0,否则-release不会执行。即便如此,解除xyz这样的做法也是不好的做法,因为xyz可能仍归其他人所有。

您应该只分配xyz一次,如果您-copy要替换xyz,则始终-release旧的xyz。始终遵循Cocoa内存管理规则。

如果您确实需要对xyz采用多个所有权,并使用单独的整数ivar来记录您保留-release的次数,那么您拥有正确的-dealloc个数字{{1}}。