Если вы хоть раз занимались разработкой программного обеспечения под iPhone, то наверняка встречались с ошибкой EXC_BAD_ACCESS. Отловить ее достаточно непросто, т.к. встроенный дебагер не покажет вам нужный стектрейс и тем более не подскажет, как все исправить.
Что же такое EXC_BAD_ACCESS? Мне удобнее сравнивать эту ошибку с NullPointerException в Java, т.к. возникает она в ситуации, когда вы отправляете "сообщение" объекту, который уже был выгружен из памяти (released). Например, попробуйте создать объект с помощью alloc и затем два раза подряд его "отпустить" с помощью release.
Так как же быть, если у нас достаточно большой проект с массой кода и объектов? Как проще и быстрее отловить данную ошибку? На помощь придет директива NSZombiEnabled, установленная в переменных окружения проекта. Все, что она сделает - это заставит Objective C runtime оставлять объект-пустышку за каждым выгруженным реальным объектом и в следующий раз, когда вы попытаетесь обратиться к своему выгруженному объекту, вызов пойдет именно к пустышке, которая остановит выполнение кода и выведет короткое и ясное сообщение в дебагер о том, какой объект был вызван и что за сообщение ему было отправлено. Стектрейс при этом также не будет испорчен, и сможет дать дополнительную информацию о месте баги.
Чтобы установить данную переменную, откройте Xcode, меню Project --> Edit Active Executable. Далее выберите вкладку Arguments, во втором списке добавьте переменную NSZombieEnabled и поставьте ей значение YES в столбце Value. Убедитесь, что перед названием переменной стоит галка.
В моем примере помимо NSZombieEnabled установлены еще две переменные: NSAutoreleaseFreedObjectCheckEnabled и NSDebugEnabled. Первая предотвратит автоматическую выгрузку из памяти объектов, помеченных как autorelease в случае, когда они уже были выгружены ранее. Вторая переменная будет полезна скорее самому разработчику, т.к. ее можно будет использовать в своем коде, когда нужно, например, вывести дополнительную информацию в debug log:
NSLog(@"Some debug info...");
}
После того, как проблема решена, не забудьте снять галки с этих переменных, т.к. нам не нужно, чтобы память в работающем приложении тратилась на дополнительные дебажные объекты.

Да, часа два мучался (ну новичок я в Objective C) с этим Бэд Аксессом. Под конец набрал в Яндексе. Первый клик - Ваш пост - 10 секунд и проблема понята. Еще пару минут - и устранена в коде :) Спасибо.
спасибо за пост
спасибо, оч полезно!
Спасибо! Реально помогло найти багу.
Хороший и полезный блог у Вас получается.
Респект и уважуха!
Отправить комментарий