Утечки памяти на объектах автоматического выпуска? - PullRequest
0 голосов
/ 17 марта 2011

Я запускаю инструменты, чтобы обнаружить утечки памяти в моем приложении для iPhone.

Как вы можете видеть на скриншоте ниже, я получаю некоторые странные утечки памяти из некоторых объектов Foundation.

Screenshot form Instruments

Больше всего меня беспокоит тот, который должен быть выпущен "автоматически", если я правильно понял. Такие как: предикат NSPredicateWithFormat, NSKeyedUnarchiver unarchiveObjectWithData и т. Д. *

Вот снимок экрана с дополнительной информацией для NSPredicate: enter image description here

Не могли бы вы помочь мне понять, что я делаю не так?

В коде я просто делаю это:

NSPredicate *basePredicate = [NSPredicate predicateWithFormat:@"ANY fcLists IN %@", listsIds];

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:self.context];
[self.fetchRequest setEntity:entity];

// Load the list of new items
NSPredicate *addedPredicate = [NSPredicate predicateWithFormat:@"fcStatus = -2"];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:basePredicate, addedPredicate, nil]];
[self.fetchRequest setFetchLimit:self.nbOfNewItems];
[self.fetchRequest setPredicate:predicate];
tmp = [self.context executeFetchRequest:self.fetchRequest error:&error];

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

Заранее благодарю за помощь!

1 Ответ

1 голос
/ 18 мая 2011

Модель сохранения / выпуска не похожа (например, на malloc / free). Недостаточно сбалансировать создание вашего объекта с выпуском или использовать метод, который возвращает автоматически выпущенные объекты. Каждое retain на объекте должно быть сбалансировано с release. Если вы пропустите только один, объект просочился. Инструменты указывают, где был создан объект, но не там, где он просочился. Инструменты указывают на каждое удержание, но не указывают (и не могут) указывать, какое удержание не сбалансировано должным образом.

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

Предположим, basePredicate протекает:

  1. Этот самый простой случай утечки basePredicate заключается в том, что вы просто не вызвали release для него. Однако в этом случае вы создаете его с помощью метода, который возвращает автоматически освобожденный объект.
  2. Следующая возможность состоит в том, что вы предоставляете другому объекту долю владения в basePredicate (то есть он вызывает retain). Этот объект не выпускает его.
  3. Следующая возможность состоит в том, что вы предоставляете другому объекту долю владения в basePredicate, как указано выше, но этот объект действительно освобождает его. Возможно, объект передает basePredicate другому объекту, который претендует на владение им, сохраняя его.
  4. Далее, возможно, что объект, которому вы дали право собственности, сам по себе утечка.
  5. Существует почти бесконечное количество перестановок последних трех сценариев.

Если это звучит ужасно, это отчасти так. Но исправление на самом деле простое: убедитесь, что каждый раз, когда ваш код заявляет о владении объектом с retain (или присваивании свойству с сохранением), он имеет соответствующий выход владение, в виде release или autorelease (или присвоение ноль собственности).

В прошлом, когда у меня была утечка, которую я просто не могу найти, я находил, что лучшее, что нужно сделать, это изучить, какие объекты утекут, и определить, какие (если они есть) отношения у них есть. Затем я просматриваю свой код и ищу объекты, которые я не выпустил.

Также, если вы еще этого не сделали, начните использовать статический анализатор. Он не может найти все проблемы, подобные этой, но когда он найдет проблему, вы сэкономите много времени.

...