Утечка памяти в iPhone NSMutableArray - PullRequest
       15

Утечка памяти в iPhone NSMutableArray

1 голос
/ 26 февраля 2010

Xcode Instruments утверждает, что приведенный ниже код приводит к утечке памяти. Насколько я понимаю, при присвоении свойства происходит следующее:
* Старое значение автоматически выпущено
* Новое значение сохраняется
* Новое значение назначено явно
Имея это в виду, почему у меня утечка памяти и как ее устранить?

"TestProjectViewController.h":

#import <UIKit/UIKit.h>

@interface TestProjectViewController : UIViewController {
    NSMutableArray* array;
}

@property (nonatomic, retain) NSMutableArray* array;

@end

"TestProjectViewController.m":

#import "TestProjectViewController.h"

@implementation TestProjectViewController

@synthesize array;

- (void)applicationDidFinishLaunching:(UIApplication *)application {    
    for(int i = 0; i < 5; i++) {
        self.array = [[NSMutableArray alloc] init];
        [self.array addObject:@"Hello world #1"];
        [self.array addObject:@"Hello world #2"];
    }
}

Ответы [ 4 ]

5 голосов
/ 26 февраля 2010
self.array = [[NSMutableArray alloc] init];

Здесь вы сохраняете новый объект массива дважды - когда выделяете его, а затем в методе установки. Это должно исправить одно из следующих действий:

self.array = [[[NSMutableArray alloc] init] autorelease];
// or
self.array = [NSMutableArray arrayWithCapacity:someNumber];

и также не забудьте освободить ваш массив методом dealloc.

1 голос
/ 14 августа 2012

Вы инициализируете массив внутри цикла. В этом нет необходимости, по крайней мере, вы присваиваете значение массива другому объекту. В этом случае вам также придется освободить его внутри цикла. Вы тоже не освобождаете память. Поскольку вы выделили память для массива, вы также должны освободить ее:

- (void)applicationDidFinishLaunching:(UIApplication *)application {    
  self.array = [[NSMutableArray alloc] init];//You just need to initialize the array just once
  for(int i = 0; i < 5; i++) {
    [self.array addObject:@"Hello world #1"];
    [self.array addObject:@"Hello world #2"];
  }
}
//Finally its necessary to release the memory when the app quits using the release method 
[self.array release]
1 голос
/ 26 февраля 2010

Каждый раз, проходя через цикл, вы alloc создаете новый массив. Каждый массив начинается с refcount 1, а присвоение свойству увеличивает его до 2. Вам нужно release этих массивов, чтобы свойство было единственным «владельцем» объекта.

Например, вы можете сделать это:

- (void)applicationDidFinishLaunching:(UIApplication *)application {    
    for(int i = 0; i < 5; i++) {
        self.array = [[NSMutableArray alloc] init];
        [self.array addObject:@"Hello world #1"];
        [self.array addObject:@"Hello world #2"];
        [self.array release];
    }
}

или сделайте это:

- (void)applicationDidFinishLaunching:(UIApplication *)application {    
    for(int i = 0; i < 5; i++) {
        self.array = [[[NSMutableArray alloc] init] autorelease];
        [self.array addObject:@"Hello world #1"];
        [self.array addObject:@"Hello world #2"];
    }
}
0 голосов
/ 26 февраля 2010

Этот метод имеет утечку, потому что alloc/init имеет неявное сохранение, а затем свойство сохраняет его еще раз. Это приводит к тому, что каждый массив сохраняется дважды. Вы можете либо autorelease массив, либо release его в конце цикла.

В качестве примечания, почему вы присваиваете подобное свойство в цикле? Только последний массив останется в этом свойстве. Вместо этого вы можете использовать локальную переменную и назначить только последний массив:

- (void)applicationDidFinishLaunching:(UIApplication *)application { 
    NSMutableArray *tempArray = nil;

    for(int i = 0; i < 5; i++) {
        tempArray  = [[[NSMutableArray alloc] init] autorelease];
        [tempArray addObject:@"Hello world #1"];
        [tempArray addObject:@"Hello world #2"];
    }

    self.array = tempArray;
}
...