Какой тип утечек не предотвращает или минимизирует автоматический подсчет ссылок в Objective-C? - PullRequest
233 голосов
/ 07 июня 2011

На платформах Mac и iOS утечки памяти часто вызваны невыпущенными указателями.Традиционно всегда было крайне важно проверять ваши ресурсы, копии и хранилища, чтобы убедиться, что у каждого есть соответствующее сообщение о выпуске.

В инструментальной цепи, которая поставляется с Xcode 4.2, введен автоматический подсчет ссылок (ARC) с последнимиверсия LLVM-компилятора , которая полностью решает эту проблему, заставляя компилятор управлять памятью за вас.Это довольно круто, и это сокращает много ненужного, обыденного времени разработки и предотвращает множество неосторожных утечек памяти, которые легко исправить с надлежащим балансом сохранения / выпуска.Даже пулы автоматического выпуска необходимо управлять по-разному, когда вы включаете ARC для своих приложений Mac и iOS (поскольку вам больше не нужно выделять свои NSAutoreleasePool).

Но что такое другая памятьУтечки не препятствуют тому, что мне все еще нужно следить?

В качестве бонуса, каковы различия между ARC в Mac OS X и iOS и сборкой мусора в Mac OS X

Ответы [ 5 ]

261 голосов
/ 17 июня 2011

Основная проблема, связанная с памятью, о которой вам еще нужно знать, это сохранение циклов. Это происходит, когда один объект имеет сильный указатель на другой, но целевой объект имеет сильный указатель на оригинал. Даже если все другие ссылки на эти объекты будут удалены, они все равно будут держаться друг за друга и не будут освобождены. Это также может происходить косвенно, когда цепочка объектов может иметь последний в цепочке, ссылающийся на более ранний объект.

По этой причине существуют квалификаторы владения __unsafe_unretained и __weak. Первый не будет сохранять какой-либо объект, на который он указывает, но оставляет открытой возможность того, что этот объект исчезнет, ​​и он указывает на плохую память, тогда как последний не сохраняет объект и автоматически устанавливает ноль, когда его цель освобождается. Из этих двух, __weak обычно предпочтительнее на платформах, которые его поддерживают.

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

Еще одна важная проблема, связанная с памятью, связана с обработкой объектов Core Foundation и памяти, выделенной с использованием malloc() для таких типов, как char*. ARC не управляет этими типами, только объектами Objective-C, поэтому вам все равно придется разбираться с ними самостоятельно. Базовые типы Foundation могут быть особенно хитрыми, потому что иногда их необходимо соединить с соответствующими объектами Objective-C и наоборот. Это означает, что управление должно быть передано и обратно от ARC при соединении между типами CF и Objective-C. Некоторые ключевые слова, связанные с этим мостовым соединением, были добавлены, и у Майка Эша есть отличное описание различных случаев мостового соединения в его длительной статье ARC .

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

Большая часть нового поведения, основанного на хранении объектов до тех пор, пока на них есть сильный указатель, очень похожа на сборку мусора на Mac. Тем не менее, технические основы очень разные. Вместо того, чтобы иметь процесс сборщика мусора, который запускается через регулярные промежутки времени для очистки объектов, на которые больше не указывают, этот стиль управления памятью опирается на жесткие правила сохранения / освобождения, которым мы все должны следовать в Objective-C.

ARC просто берет повторяющиеся задачи по управлению памятью, которые нам приходилось выполнять годами, и выгружает их в компилятор, поэтому нам больше не нужно о них беспокоиться. Таким образом, у вас не будет проблем с остановкой или профилей памяти пилообразной памяти, возникающих на платформах для сбора мусора. Я испытал оба этих фактора в своих приложениях Mac для сбора мусора, и мне не терпится узнать, как они ведут себя в ARC.

Подробнее о сборке мусора по сравнению с ARC см. этот очень интересный ответ Криса Латтнера в списке рассылки Objective-C , где он перечисляет многие преимущества ARC по сравнению с сборкой мусора Objective-C 2.0. Я столкнулся с несколькими проблемами GC, которые он описывает.

14 голосов
/ 22 ноября 2011

ARC не поможет вам с не-ObjC памятью, например, если вы malloc() что-то, вам все еще нужно free() это.

ARC может быть одурачен performSelector:, если компилятор не может определить, что это за селектор (компилятор выдаст предупреждение об этом).

ARC также будет генерировать код в соответствии с соглашениями об именах ObjC, поэтому, если вы смешаете код ARC и MRC, вы можете получить удивительные результаты, если код MRC не выполнит то, что компилятор считает именами.

7 голосов
/ 07 июня 2015

В приложении возникли утечки памяти из-за следующих 4 проблем:

  1. Не делает недействительными NSTimers при отклонении контроллеров представления
  2. Забывает удалить любых наблюдателей в NSNotificationCenter при отключении контроллера представления.
  3. Сохранение сильных ссылок на себя в блоках.
  4. Использование строгих ссылок на делегатов в свойствах контроллера представления

К счастью, я наткнулся на следующее сообщение в блоге и смог их исправить: http://www.reigndesign.com/blog/debugging-retain-cycles-in-objective-c-four-likely-culprits/

0 голосов
/ 12 апреля 2018

Xcode 9 предоставляет отличный инструмент для поиска подобных проблем.Он называется: " График отладочной памяти ".Используя его, вы можете найти свой просочившийся объект по типу класса и четко увидеть, кто на него ссылается, выпуская его оттуда, решает вашу проблему.Он также обнаруживает циклы памяти.

Подробнее о том, как его использовать

0 голосов
/ 18 января 2013

ARC также не будет управлять типами CoreFoundation.Вы можете «соединить» их (используя CFBridgingRelease()), но только если вы собираетесь использовать его как объект Objective-C / Cocoa.Обратите внимание, что CFBridgingRelease просто уменьшает счетчик сохранения CoreFoundation на 1 и перемещает его в ARC Objective-C.

...