2011-04-01 45 views
2

我對iOS內存管理感到困惑。我有一個具有NSMutableArray類型成員的類。當將這種類型的對象存儲在另一個數組中並將其刪除時,Instruments將顯示所有這些成員泄漏內存。這是我的流氓類的定義:如何正確地釋放一個NSMutableArray與具有一個NSMutableArray成員與NSNumber對象內的對象?

@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]; 

運行這段代碼泄漏內存和儀器顯示泄漏存儲器分配在線:

cop.others = [others mutableCopy]; 

我做錯了什麼?

回答

3
cop.others = [others mutableCopy] 

其他被聲明爲保留的性質,因此分配給它建立在新的價值的所有權要求。 -mutableCopy是一種隱含所有權的方法(因爲它包含單詞「copy」)。所以你現在有兩個所有權聲明,兩者都必須發佈。推薦的方式做,這是第一個將副本分配到一個臨時變量,然後分配給你的財產,釋放它,就像這樣:

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

你也可以做這一步,避免臨時對象,儘管這樣做使用自動釋放池,並且效率略低於此:

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

謝謝。這就說得通了。自儀器向我指出問題出在哪裏以後,我應該自己想清楚了。 – Mayoneez 2011-04-01 17:25:42

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 
相關問題