如何正确释放NSMutableArray与具有NSMutableArray成员与NSNumber对象里面的对象?

时间:2011-04-01 14:21:47

标签: iphone objective-c sdk nsmutablearray release

我对iOS内存管理感到困惑。我有一个类,其成员类型为NSMutableArray。当将此类型的对象存储在另一个阵列中并将其删除时,Instruments会显示所有这些成员都会泄漏内存。这是我的流氓类的定义:

@interface Tester : NSObject {
  int some;
  NSMutableArray* others;
}
@property int some;
@property (nonatomic, retain) NSMutableArray* others;
-(id)init;
-(id)copy;
-(void)dealloc;
@end

这是流氓类的实现:

@implementation Tester

@synthesize some;
@synthesize others;

-(id)init {
  self = [super init];
  if(self) {
    some = 0;
    others = [[NSMutableArray alloc] initWithCapacity:5];
    int i;
    for(i = 0; i < 5; ++i) {
      [others addObject:[NSNumber numberWithInt:i]];
    }
  }
  return self;
}

-(id)copy {
  Tester* cop = [[Tester alloc] init];
  cop.some = some;
  cop.others = [others mutableCopy]
  return cop;
}

-(void)dealloc {
  [others removeAllObjects];
  [others release];
  [super dealloc];
}
@end

以下是我测试的方法:

NSMutableArray* container = [[NSMutableArray alloc] init];
Tester* orig = [[Tester alloc] init];
int i;
for(i = 0; i < 10000; ++i) {
  Tester* cop = [orig copy];
  [container addObject:cop];
}
while([container count] > 0) {
  [[container lastObject] release];
  [container removeLastObject];
}
[container release];

运行此代码会泄漏内存,而Instruments会显示泄漏的内存分配在以下行:

cop.others = [others mutableCopy];

我做错了什么?

2 个答案:

答案 0 :(得分:4)

您正在创建一个副本:[others mutableCopy]您拥有但忘记发布。该行应该是:

cop.others = [[others mutableCopy] autorelease];

如果您让container数组成为Tester对象的唯一所有者,那么测试代码会更清晰:

NSMutableArray* container = [[NSMutableArray alloc] init];
Tester* orig = [[Tester alloc] init];
for (int i = 0; i < 10000; ++i)
    [container addObject:[[orig copy] autorelease]];

while([container count] > 0)
    [container removeLastObject];

[container release];

现在你可以删除清空容器的循环。

或者你可以跳过容器:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

Tester* orig = [[[Tester alloc] init] autorelease];
for (int i = 0; i < 10000; ++i)
    [[orig copy] autorelease];

[pool drain]; // At this point all Tester objects are released

答案 1 :(得分:3)

cop.others = [others mutableCopy]

其他人被宣布为保留财产,因此分配给新财产的所有权声明。 -mutableCopy是一种暗示所有权的方法(因为它包含单词“copy”)。因此,您现在拥有两个所有权声明,这两个声明都必须发布。建议的方法是首先将副本分配给临时变量,然后将其分配给您的属性并释放它,如下所示:

NSMutableArray *tmpArray = [others mutableCopy];
cop.others = tmpArray;
[tmpArray release];

您也可以一步完成此操作,避免临时对象,尽管这样做会使用自动释放池,因此效率稍低:

cop.others = [[others mutableCopy] autorelease];