Проблема с отладкой Xcode и ARC (пропуск сделки)

Я потратил некоторое время на отладку странной проблемы с ARC и пользовательскими функциями Dealloc.

  1. Я создаю подкласс NSOperation класса
  2. Я установил блок завершения для этой операции
  3. На операцию ссылается сильное свойство очень плоского объекта (без методов, автоматических ivars, два сильных свойства), назовем этот объект DataRequest
  4. следуя всем рекомендациям, блок завершения использует только слабые ссылки на локальные объекты (включая саму операцию)
  5. ни компилятор, ни анализатор не вызывают никаких проблем
  6. DataRequest содержит ЕДИНСТВЕННУЮ ссылку на операцию, которую я генерирую, и уничтожается в блоке завершения операции. Он ВСЕГДА уничтожается (его dealloc всегда выполняет)
  7. Моя операция имеет пользовательский файл dealloc. У меня есть только один вызов NSLog.

... и проблема в следующем:

Если я запускаю это в отладчике, точка останова в Dealloc никогда не срабатывает, сообщение журнала никогда не появляется. Сначала я думал, что операция протекла.

Если я запускаю это в инструментах, все в порядке, системная консоль печатает сообщение, а инструмент распределения сообщает об освобождении операции из надлежащего моментального снимка стека, включая пользовательскую сделку. Утечек не обнаружено.

Я на 100% уверен, что использую одни и те же настройки компилятора для отладки и профилирования.

Самое запутанное в конце: Если я создаю кастомную версию [DataRequest dealloc] и ставлю ей self.operation = nil; - все нормально работает даже из отладчика.

Есть ли у кого-нибудь подсказки, какие параметры компоновщика компилятора попробовать, чтобы увидеть разницу? может ли это быть ошибкой в ​​инструментах Apple (все мы были в состоянии обвинить большую рыбу в наших собственных ошибках, верно?)

... и да, я пробовал с GDB и LLDB. Результат был тот же - что может на что-то указывать.

Я попытался создать минималистичный образец, но он просто сработал (действительно) ;)

Спасибо


person simpleone    schedule 13.10.2011    source источник
comment
Я сделал очень простое наблюдение... если я запускаю приложение на симуляторе из XCode (GDB или LLDB), мои сообщения журнала в dealloc не печатаются. Если я просто выйду из отладчика и запущу приложение прямо из симулятора - Console.app покажет все сообщения. Нет компиляции, нет промежуточных ссылок. Странный.   -  person simpleone    schedule 13.10.2011
comment
... и один еще более простой результат... Если я запускаю приложение из XCode в сеансе отладки - Dealloc не вызывается (журнал не печатается), если я запускаю приложение вручную в симуляторе, а затем подключаю отладчик... все как и ожидалось.   -  person simpleone    schedule 13.10.2011


Ответы (3)


У вас есть NSZombiesEnabled? У нас была такая же проблема, и мы «решили» ее, отключив NSZombies.

"Продукт" -> "Схема" -> "Редактировать схему" -> "Диагностика" -> Снимите флажок "Включить объекты-зомби"

Я не уверен, почему Dealloc не вызывается при включении NSZombies (я почти уверен, что он был вызван до ARC).

person Ray Lillywhite    schedule 21.10.2011
comment
Я должен проверить - но да, у меня установлен NSZombiesEnabled. Это звучит вполне вероятно — и, по крайней мере, дает какое-то разумное объяснение различному поведению. - person simpleone; 31.10.2011
comment
Я могу подтвердить, что проблема связана с NSZombiesEnabled. Большое спасибо! - person simpleone; 31.10.2011
comment
Это может произойти повсеместно при использовании NSZombiesEnabled с ARC, а не только с NSOperation. Ключевым моментом при наблюдении за странностями расщепления с помощью ARC является отключение NSZombiesEnabled (который помечен как Enabled Zombie Objects в схемах редактирования... › вкладка «Диагностика» в Xcode 4.) - person Jonathan Ellis; 14.12.2011
comment
Причина, по которой не вызывается Dealloc, заключается в том, что объект никогда не освобождается. Ему не дают этого сделать, и вместо этого он превращается в зомби. - person borrrden; 24.10.2012
comment
@borrrden Я думаю, что его можно было бы освободить и просто заменить объектом-зомби по тому же адресу. Насколько я знаю, так это работало до арки. - person Ray Lillywhite; 01.11.2012
comment
@RayLillywhite Возможно, ты прав. Я не помню, был ли вызван Dealloc или нет, сейчас, когда я думаю об этом. Я только помню, что память фактически не освобождалась и в Инструментах это показывалось плохо. - person borrrden; 01.11.2012

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

Я также согласен с тем, что до ARC в этом случае вызывалась Dealloc.

После многих тестов выяснилось, что Dealloc не вызывается при использовании iOS 5.x (устройство или симулятор).

но он вызывается снова (с включенными зомби) в iOS 6.x (устройство или симулятор)

Я не знаю, вызвано ли это изменение ошибкой в ​​ios5, которая была исправлена ​​в ios6, или добавленной функцией, которая откатывается.

Надеюсь, это поможет...

person poloDelaVega    schedule 15.02.2013

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

Если вы используете блоки:

  1. Убедитесь, что SELF не появляется внутри блока.
  2. Если вам нужно использовать SELF внутри блока, используйте слабую ссылку.
  3. Убедитесь, что внутри блока нет макросов, которые могут ссылаться на себя (например, NSAssert).
person Nicolas Jakubowski    schedule 29.03.2014