Утечка памяти с помощью [NSKeyedUnarchiver decodeObjectForKey] - PullRequest
3 голосов
/ 04 октября 2008

Каждый раз, когда я вызываю этот метод, моя NSMutableData протекает, и я не могу понять, как его подключить. количество сохраненных данных увеличивается на единицу после того, как декодер выделен и инициализирован, и я понятия не имею, почему. Я застрял с сохранением счетчика 2 в конце метода, и попытка освободить его вызывает сбой приложения.

- (void)readVenueArchiveFile:(NSString *)inFile key:(NSString *)inKey
{
    NSMutableData *theData;
    NSKeyedUnarchiver *decoder;


    theData = [NSData dataWithContentsOfFile:inFile];

    decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];

    venueIOList = [[decoder decodeObjectForKey:inKey] mutableCopy];

    [decoder finishDecoding];

    [decoder release];
}

Ответы [ 5 ]

4 голосов
/ 06 октября 2008

Уменьшение пиковой нагрузки на память

Как правило, рекомендуется избегать генерации автоматически выпущенных объектов.

[Большая часть этого абзаца изменена с на этот вопрос .] Поскольку вы обычно (1) не имеете прямого контроля над их временем жизни, автоматически выпущенные объекты могут сохраняться в течение сравнительно длительного времени и излишне увеличивать память след вашей заявки. В то время как на рабочем столе это может иметь незначительные последствия, на более ограниченных платформах это может быть серьезной проблемой. Поэтому на всех платформах, и особенно на более ограниченных платформах, вам, по возможности, не рекомендуется использовать методы, которые могут привести к автоматическому освобождению объектов, и вместо этого рекомендуется использовать шаблон alloc / init.

Я бы предложил заменить это:

theData = [NSData dataWithContentsOfFile:inFile];

с:

theData = [[NSData alloc] initWithContentsOfFile:inFile];

затем в конце метода добавьте:

[theData release];

Это означает, что theData будет освобожден до выхода из метода. Вы должны в конечном итоге:

- (void)readVenueArchiveFile:(NSString *)inFile key:(NSString *)inKey
{
    NSMutableData *theData;
    NSKeyedUnarchiver *decoder;

    theData = [[NSData alloc] initWithContentsOfFile:inFile];
    decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
    ListClassName *decodedList = [decoder decodeObjectForKey:inKey];
    self.venueIOList = decodedList;
    [decoder finishDecoding];
    [decoder release];
    [theData release];

}

Это делает семантику управления памятью понятной и восстанавливает память как можно быстрее.

(1) Вы можете получить контроль, используя свои собственные локальные пулы автоматического выпуска. Подробнее об этом см. Руководство по программированию управления памятью Apple .

3 голосов
/ 04 октября 2008

Я бы предложил заменить эту строку:

venueIOList = [[decoder decodeObjectForKey:inKey] mutableCopy];

с:

ListClassName *decodedList = [decoder decodeObjectForKey:inKey];
self.venueIOList = decodedList;

Это делает управление памятью decodedList понятным. Рекомендуется назначать переменные экземпляра с помощью метода доступа (кроме методов init). В вашей текущей реализации, если вы когда-нибудь вызовете readVenueArchiveFile: во второй раз для того же объекта, вы будете иметь утечку (как вы это сделаете, если decodedList уже имеет значение). Более того, вы можете поместить логику копирования в свой метод доступа и забыть об этом, вместо того, чтобы запоминать mutableCopy каждый раз, когда вы присваиваете новое значение (при условии, что в любом случае есть хорошая причина сделать изменяемую копию?).

2 голосов
/ 04 октября 2008

Не беспокойтесь о сохранении счета, беспокойтесь о балансе в методе. То, что вы делаете в этом методе, выглядит правильно, если предположить, что venueIOList является переменной экземпляра.

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

1 голос
/ 04 октября 2008

Источником просвещения по управлению памятью, связанным с refcount, по-прежнему является ИМО, «Держи меня, используй меня, освободи меня» от Stepwise.

0 голосов
/ 04 октября 2008

Ваш код правильный; утечки памяти нет.

theData = [NSData dataWithContentsOfFile:inFile];

эквивалентно

theData = [[[NSData alloc] initWithContentsOfFile:inFile] autorelease];

В этот момент theData имеет счетчик ссылок 1 (если меньше, он будет освобожден). Счетчик ссылок будет автоматически уменьшен в некоторый момент в будущем за счет пула автоматического выпуска.

decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];

Объект декодера сохраняет ссылку на данные, которая увеличивает его счетчик ссылок до 2.

После возврата метода пул автоматического выпуска уменьшает это значение до 1. Если вы опустите данные в конце этого метода, счетчик ссылок станет равным 0, объект будет освобожден, и ваше приложение будет аварийно завершено при попытке используйте это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...