Как отлаживать "сообщение, отправленное на освобожденный экземпляр" в Xcode4?
Я нажал ALT + CMD + R и активировал NSZombieEnabled в Аргументы > Переменные среды. Кроме того, я активировал его в разделе "Диагностика" > "Управление памятью" > "Включить объекты зомби".
Однако, когда я создавал и запускал, в какой-то момент мое приложение аварийно выдавало мне это бесполезное сообщение в консоли:
*** -[CALayer retainCount]: message sent to deallocated instance 0x656b260
Трассировка стека столь же бесполезна. Я переместил ползунок уровня детализации до упора вправо. Тема 1 просто показывает мне это:
![screenshot]()
Все принадлежит системе и нет ни одной строки, связанной с моим приложением. Таким образом, очевидно, NSZombiesEnabled не работает так, как в Xcode 3, где он остановился на мертвом объекте.
Есть ли способ выяснить, какой CALayer освобожден слишком рано?
Обновление: поэтому после создания и запуска еще 100 раз внезапно проблема DISAPPEARED! Он полностью ушел! И лучшая часть: я никак не изменял свой код! В промежутке я несколько раз очищал папку сборки и проецировал чистые команды и несколько раз удалял приложение в Симуляторе.
Обновление 2: К счастью, проблема снова появилась. И теперь это кажется настойчивым. К счастью, потому что я предпочитаю находить первопричину, а не раздражать пользователей случайным образом.
Обновление 3: Наконец-то это произошло случайно:
startButton = newBttn;
должен был быть:
self.startButton = newBttn;
startButton был сохраняющим свойством, а в -dealloc я его выпустил. Таким образом, он был переименован и в большинстве (но не во всех) случаях после того, как взгляд исчез, он разбился, давая это странное сообщение CALayer keepCount.
Инструмент Зомби (CMD + I), наконец, указал, что это связано с кнопкой. Просто не знал, почему и где.
Статический анализатор Clang не жаловался на этот очевидный сбой.
Ответы
Ответ 1
Если это снова появится, вы можете запустить специальный инструмент Zombies. Hit Command + I, чтобы профилировать приложение и выбрать инструмент Zombies (вы должны работать на симуляторе). Если вы получаете зомби, вы можете отобразить всю историю памяти (каждый сохранить/освободить) для этого объекта, что очень полезно при отслеживании ошибок.
Ответ 2
В дополнение к Джеффу большой ответ; сделать практически то же самое, но без необходимости открывать инструменты или профиль вашего приложения, вы можете установить NSZombieEnabled, MallocStackLogging и guard malloc в отладчике. Затем, когда ваше приложение выйдет из строя, введите его в консоли gdb:
(gdb) info malloc-history 0x543216
Замените 0x543216
адресом объекта, который вызвал сбой, и вы получите гораздо более полезную трассировку стека, и это поможет вам точно определить точную строку в коде, вызывающую проблему.
В этой статье есть дополнительная информация.