Управление переменной памяти экземпляра NSMutableArray - PullRequest
2 голосов
/ 01 апреля 2011

Я делаю последний урок по управлению памятью, и есть кое-что, чего я не понимаю.Я проверил всю документацию, переполнение стека и т. Д., Но до сих пор не получил.Я подозреваю, что это связано с массивами.

У меня есть NSMutableArray в качестве переменной экземпляра, которую я использую для хранения объектов, созданных из объектов в другом массиве.

-viewDidLoad инициализирует массив какследует:

self.photoAlbum = [[NSMutableArray alloc] initWithCapacity:100];

Затем вызывается метод, который их заполняет.

int i = 0;
for (Gem *gem in self.entityArray) {
    NSString * filePath = [[NSString alloc] initWithFormat: @"%@/%@2.jpg", [sysPaths objectAtIndex: 0], gem.detailsTitle];  
    // there is some stuff in here that means that there isn't a one to one relationship between the objects in gem and those in photo
    Photo *photo = [[Photo alloc] init];
    photo.filePath = filePath;
    photo.title = gem.title;
    photo.index = [NSNumber numberWithInt:i];
    [self.photoAlbum addObject:photo];
    [filePath release];
    [photo release];
    i++;
}

В инструментах он показывает, что у меня есть утечка Photo объектов, и я не уверен, почему.

Свойство photoAlbum:

@property (nonatomic, retain) NSMutableArray *photoAlbum;

Чего мне не хватает?

Ответы [ 2 ]

7 голосов
/ 01 апреля 2011

Проблема в том, что установщик вашего свойства имеет retain семантику. Вам нужно autorelease при настройке свойства, например:

self.photoAlbum = [[[NSMutableArray alloc] initWithCapacity:100] autorelease];

или, еще лучше:

self.photoAlbum = [NSMutableArray arrayWithCapacity:100];

Причина этого в том, что создатель, который вы сгенерировали, синтезируя это свойство, выглядит примерно так (упрощенно):

- (void)setPhotoAlbum:(NSMutableArray *)array {
  [photoAlbum autorelease];
  photoAlbum = [array retain];
}

Итак, что происходит:

[photoAlbum autorelease];
photoAlbum = [[[NSMutableArray alloc] initWithCapacity:100] retain]; // 0 + 2 = 2

// in -dealloc:
[photoAlbum release]; // 2 - 1 = 1

Следовательно, photoAlbum никогда не освобождается достаточное количество раз для освобождения, поскольку -release выглядит примерно так (сильно упрощенно):

- (void)release {
  retainCount = retainCount - 1;
  if (retainCount == 0) {
    [self dealloc];
  }
}

(Я хочу повторить, что это в основном то, что делает реализация, а не то, как она выглядит в реальной жизни). Дело в том, что вы не будете инициировать освобождение, пока не уравновесите свои релизы с вашими удержаниями.

Не воспринимайте это как призыв к КАЖДОМУ взгляду на -retainCount, никогда, никогда. Другие объекты, существующие во время выполнения, могут сохранять ваш объект и делать с ним вещи, о которых вы не знаете; следовательно, фактический счетчик вашего объекта в любой момент времени для вас бесполезен. Пожалуйста, никогда, никогда не используйте его при управлении памятью. @bbum поблагодарит вас.

0 голосов
/ 01 апреля 2011

Вы, вероятно, пропали без вести

[photoAlbum release];

в методе dealloc.

Редактировать

На самом деле, я был неправ. Проблемная линия -

self.photoAlbum = [[NSMutableArray alloc] initWithCapacity:100];

Массив, который вы создаете, принадлежит вам, но вы его не освобождаете Это исправит это:

self.photoAlbum = [[[NSMutableArray alloc] initWithCapacity:100] autorelease];
...