В тот или иной момент вы столкнетесь с аварией, вызванной EXC_BAD_ACCESS . В этом кратком совете вы узнаете, что такое EXC_BAD_ACCESS и чем оно вызвано. Я также дам вам несколько советов, чтобы исправить ошибки, вызванные EXC_BAD_ACCESS.
1. Что такое EXC_BAD_ACCESS?
Как только вы поймете причину EXC_BAD_ACCESS, вы лучше поймете его загадочное имя. Есть простое объяснение и более техническое объяснение. Давайте начнем с простого объяснения.
Сохраняя это простым
Всякий раз, когда вы сталкиваетесь с EXC_BAD_ACCESS, это означает, что вы отправляете сообщение объекту, который уже был освобожден. Это наиболее распространенный сценарий, но есть исключения, о которых мы поговорим чуть позже.
Что это на самом деле означает
Техническое объяснение немного сложнее. В C и Objective-C вы постоянно имеете дело с указателями . Указатель — это не более чем переменная, в которой хранится адрес памяти другой переменной. Когда вы отправляете сообщение объекту, указатель, указывающий на объект, на который вы отправляете сообщение, должен быть разыменован . Это означает, что вы берете адрес памяти, на который указывает указатель, и получаете доступ к значению этого блока памяти.
Когда этот блок памяти больше не отображается для вашего приложения или, другими словами, этот блок памяти не используется для того, что, как вы думаете, он использует, больше невозможно получить доступ к этому фрагменту памяти. Когда это происходит, ядро отправляет исключение ( EXC ), указывающее, что ваше приложение не может получить доступ к этому блоку памяти ( BAD ACCESS ).
Таким образом, когда вы сталкиваетесь с EXC_BAD_ACCESS, это означает, что вы пытаетесь отправить сообщение в блок памяти, который не может выполнить это сообщение.
Однако в некоторых случаях EXC_BAD_ACCESS вызван поврежденным указателем. Всякий раз, когда ваше приложение пытается разыменовать поврежденный указатель, ядром генерируется исключение.
2. Отладка EXC_BAD_ACCESS
Отладка EXC_BAD_ACCESS может быть сложной и неприятной. Однако теперь, когда EXC_BAD_ACCESS больше не является для вас загадкой, она должна быть менее пугающей.
Первое, что вам нужно понять, это то, что ваше приложение не обязательно аварийно завершает работу, когда блок памяти больше не доступен вашему приложению. Именно это часто затрудняет отладку EXC_BAD_ACCESS.
То же самое относится и к коррумпированным указателям. Ваше приложение не будет зависать, потому что указатель поврежден. Это также не приведет к сбою, если вы передадите поврежденный указатель в вашем приложении. Однако, когда ваше приложение пытается разыменовать поврежденный указатель, все идет не так.
Zombies
Хотя зомби приобрели популярность за последние несколько лет, они существуют в XCode уже более десяти лет. Название зомби может показаться немного драматичным, но на самом деле это отличное название для функции, которая поможет нам отладить EXC_BAD_ACCESS. Позвольте мне объяснить, как это работает.
В Xcode вы можете включить объекты зомби, что означает, что освобожденные объекты хранятся как зомби. Иными словами, освобожденные объекты остаются живыми для целей отладки. В этом нет никакой магии. Если вы отправите сообщение объекту-зомби, ваше приложение все равно будет аварийно завершено в результате EXC_BAD_ACCESS.
Почему это полезно? Что делает EXC_BAD_ACCESS трудным для отладки, так это то, что вы не знаете, к какому объекту ваше приложение пыталось получить доступ. Объекты зомби решают эту проблему во многих случаях. Поддерживая освобожденные объекты живыми, XCode может сказать вам, к какому объекту вы пытались получить доступ, что значительно облегчает поиск проблемы.
Включить зомби в Xcode очень просто. Обратите внимание, что это может отличаться в зависимости от используемой версии Xcode. Следующий подход применяется к Xcode 6 и 7. Щелкните активную схему в левом верхнем углу и выберите Edit Scheme .
Выберите Run слева и откройте вкладку Diagnostics вверху. Чтобы включить объекты-зомби, установите флажок Включить объекты-зомби .
Если вы сейчас столкнетесь с EXC_BAD_ACCESS, вывод в консоли Xcode даст вам гораздо лучшее представление о том, с чего начать поиск. Взгляните на следующий пример вывода.
1
|
2015-08-12 06:31:55.501 Debug[2371:1379247] -[ChildViewController respondsToSelector:] message sent to deallocated instance 0x17579780
|
В приведенном выше примере Xcode сообщает нам, что сообщение о respondsToSelector:
было отправлено объекту зомби. Однако объект zombie больше не является экземпляром класса ChildViewController
. Блок памяти, ранее выделенный экземпляру ChildViewController
больше не отображается для вашего приложения. Это должно дать вам довольно хорошее представление о том, что является основной причиной проблемы.
К сожалению, объекты зомби не смогут сохранить ваш день для каждого сбоя, вызванного EXC_BAD_ACCESS. Если зомби-объекты не справляются, то пришло время для некоторого надлежащего анализа.
анализировать
Если объекты-зомби не решают вашу проблему, то основная причина может быть менее тривиальной. В этом случае вам нужно внимательнее взглянуть на код, который выполняется при сбое приложения. Это может быть громоздким и трудоемким.
Чтобы помочь вам найти проблемы в вашей кодовой базе, вы можете попросить Xcode проанализировать ваш код, чтобы помочь вам найти проблемные области. Обратите внимание, что Xcode анализирует ваш проект, что означает, что он укажет на каждую потенциальную проблему, с которой он сталкивается.
Чтобы заставить Xcode проанализировать ваш проект, выберите « Анализ» в меню « Продукт» Xcode или нажмите Shift-Command-B . Xcode займет несколько минут, но после его завершения вы увидите список проблем в Навигаторе проблем слева. Проблемы, найденные в результате анализа, выделены синим цветом.
Когда вы нажимаете на проблему, XCode переводит вас в блок кода, который требует вашего внимания. Обратите внимание, что XCode только делает предложение. В некоторых случаях возможно, что проблема не актуальна и не требует исправления.
Если вы не можете найти ошибку, которая вызывает EXC_BAD_ACCESS, тогда важно тщательно изучить каждую проблему Xcode, обнаруженную во время анализа вашего проекта.
Вывод
EXC_BAD_ACCESS является распространенным разочарованием среди разработчиков, и это то, что присуще ручному управлению памятью. Проблемы, связанные с управлением памятью, стали менее частыми с момента появления ARC (автоматического подсчета ссылок), но они ни в коем случае не исчезли.