Проблема памяти Objective-C (iPhone) - PullRequest
2 голосов
/ 26 февраля 2009

Меня несколько смущает следующее поведение, которое я вижу в проекте Xcode, скомпилированном для симулятора (или устройства) iPhone:

NSString *test = [[NSString alloc] initWithCString:"foo"];

NSLog(@"test retain count = %d", [test retainCount]); // prints 1

[test release];

NSLog(@"test retain count = %d", [test retainCount]); // also prints 1 instead of 0

Однако любые дальнейшие попытки получить доступ к «тесту» приводят к сбою среды Xcode, будь то другой оператор [test retainCount] NSLog или другой (даже если проверяется, равен ли тест нулю).

Мысли? Скомпилировано в простом тестовом проекте на основе View ... код существует в методе applicationDidFinishLaunching проекта.

Разъяснение - я знаю, что НЕ делать выше на практике. Это был всего лишь тест, чтобы понять, почему в некоторых случаях отладки счетчик сохранения 1 фактически не отражает реального состояния объекта. Спасибо за ваши ответы. Это была просто пробная заглушка, чтобы понять, почему в некоторых случаях я наблюдаю определенное поведение. Что я действительно пытаюсь сделать, так это отследить очень маленькую утечку памяти (0,06 МБ), которая постоянно создается всякий раз, когда я уничтожаю / воссоздаю пользовательское представление.

Ответы [ 6 ]

5 голосов
/ 27 февраля 2009

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

5 голосов
/ 26 февраля 2009

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

Концентрат обеспечения вашего кода в соответствии с правилами управления памятью какао в отношении владения объектом. При необходимости используйте инструменты для проверки фактических утечек памяти.

0 голосов
/ 27 февраля 2009

Одним из способов улучшить код, показанный выше, было бы использование соглашения 'set to nil'.

EG:

NSString * test = [[NSString alloc] initWithCString: "foo"];

NSLog (@ "test retain count =% d", [test retainCount]); // печатает 1

[тестовый релиз]; тест = ноль; // установлен в ноль, так как я освободил указатель, я больше не должен его использовать.

NSLog (@ "test retain count =% d, test foobarpro =% d", [test retainCount], [test foobarPro]); // теперь будет печатать 0 и 0 - потому что любой вызов target-c для объекта nil возвращает 0 (и не завершится)

Установив указатель на ноль после того, как вы его отпустите, вы немного подтвердиете свой код на будущее: кто-то, кто придет позже и отредактирует код на 10 строк ниже, может случайно использовать «тест», вероятно, без вредных последствий (или очевидного сбоя). Я даже установил нулевые указатели в вызовах dealloc, так как некоторые из самых сложных задач отладки случаются, когда в уничтожении используются ненулевые «плохие» указатели.

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

- Том

0 голосов
/ 27 февраля 2009

Когда вы отправляете это release, строка освобождается - другие владельцы не сохраняют ее. Отправка дальнейших сообщений (включая retainCount) является ошибкой и не возвращает ничего значимого.

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

Вам следует прочитать Руководство по управлению памятью Apple , если вам неясно, по какому поводу. Это не слишком сложно и абсолютно необходимо для программирования Какао.

0 голосов
/ 26 февраля 2009

не полагайтесь на счет удержания; Вместо этого, убедитесь, что вы балансируете удерживает и отпускает. Вот некоторые ссылки на управление памятью Какао (Touch): http://iamleeg.blogspot.com/2008/12/cocoa-memory-management.html

0 голосов
/ 26 февраля 2009

Не полагайтесь на количество сохраняемых данных ... фреймворк может сохранять данные самостоятельно.

Вместо этого полагайтесь на правила управления памятью для target-C. Если вы выделяете, инициализируете или создаете что-то новое, вы являетесь его владельцем и несете ответственность за его освобождение. Если нет, то нет.

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