Получен сигнал EXC_BAD_ACCESS - PullRequest
281 голосов
/ 29 ноября 2008

При развертывании приложения на устройстве программа закроется через несколько циклов со следующей ошибкой:

Program received signal: "EXC_BAD_ACCESS".

Программа работает без проблем на симуляторе iPhone, она также будет отлаживаться и запускаться, пока я выполняю инструкции по одной за раз. Как только я снова включу его, я нажму на сигнал EXC_BAD_ACCESS.

В данном конкретном случае произошла ошибка в коде акселерометра. Он не будет выполняться в симуляторе, поэтому не выдает никаких ошибок. Тем не менее, он будет выполняться после развертывания на устройстве.

Большинство ответов на этот вопрос имеют дело с общей ошибкой EXC_BAD_ACCESS, поэтому я оставлю это открытым как универсальное средство для страшной ошибки Bad Access.

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

Вы когда-нибудь сталкивались с сигналом EXC_BAD_ACCESS и как с ним справлялись?

Ответы [ 32 ]

193 голосов
/ 30 ноября 2008

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

Помните, что все, что вы получаете от функции выделения (обычно это статический метод alloc, но есть несколько других) или метода копирования, вы тоже владеете памятью и должны освободить ее, когда закончите.

Но если вы получите что-то от чего-то еще , включая фабричные методы (например, [NSString stringWithFormat]), то у вас будет ссылка на авто-релиз, что означает, что она может быть выпущена в будущем. другим кодом - поэтому жизненно важно, чтобы, если вам нужно сохранить его вне пределов непосредственной функции, вы сохраните его. Если вы этого не сделаете, память может остаться выделенной во время ее использования или быть освобожденной, но, по совпадению, все еще действующей, во время тестирования вашего эмулятора, но с большей вероятностью будет освобождена и будет отображаться как ошибка неверного доступа при работе на устройстве.

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

99 голосов
/ 01 июля 2009

Основной причиной EXC_BAD_ACCESS является попытка доступа к освобожденным объектам.

Чтобы узнать, как решить эту проблему, прочитайте этот документ: DebuggingAutoReleasePool

Даже если вы не думаете, что «выпускаете автоматически выпущенные объекты», это относится к вам.

Этот метод работает очень хорошо. Я использую это все время с большим успехом !!

Таким образом, это объясняет, как использовать класс отладки NSZombie Какао и инструмент командной строки «malloc_history», чтобы точно определить, к какому освобожденному объекту обращались в вашем коде.

Sidenote:

Запуск инструментов и проверка на утечки не помогут устранить неполадки EXC_BAD_ACCESS. Я почти уверен, что утечки памяти не имеют ничего общего с EXC_BAD_ACCESS. Определение утечки - это объект, к которому у вас больше нет доступа, и поэтому вы не можете его вызвать.

UPDATE: Теперь я использую инструменты для отладки утечек. В Xcode 4.2 выберите Product-> Profile и при запуске Instruments выберите «Zombies».

12 голосов
/ 29 ноября 2008

Сигнал EXC_BAD_ACCESS является результатом передачи неверного указателя на системный вызов. Сегодня я получил его с тестовой программой для OS X - я передавал неинициализированную переменную в pthread_join(), что было связано с более ранней опечаткой.

Я не знаком с разработкой для iPhone, но вы должны дважды проверить все ваши указатели буфера, которые вы передаете системным вызовам. Повысьте уровень предупреждений вашего компилятора до конца (с gcc используйте опции -Wall и -Wextra). Включите как можно больше диагностики на симуляторе / отладчике.

8 голосов
/ 30 ноября 2008

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

Если ни одна из этих проверок на бумаге ничего не приводит к повышению и это не происходит при пошаговом выполнении, попытайтесь найти ошибку с помощью операторов NSLog (): посыпьте их кодом, перемещая их, пока не изолируете линия, которая вызывает ошибку. Затем установите точку останова на этой строке и запустите вашу программу. Когда вы дойдете до точки останова, изучите все переменные и объекты в них, чтобы увидеть, не выглядит ли что-нибудь не так, как вы ожидаете. Я бы особенно следил за переменными, чей класс объектов - это то, чего вы не ожидали. Если предполагается, что переменная содержит UIWindow, но вместо этого в ней есть NSNotification, та же самая ошибка базового кода может проявляться по-другому, когда отладчик не работает.

7 голосов
/ 26 октября 2009

Я просто потратил пару часов на отслеживание EXC_BAD_ACCESS и обнаружил, что NSZombies и другие env-переменные, похоже, ничего мне не говорили.

Для меня это был глупый оператор NSLog с указателями формата, но аргументы не передавались.

NSLog(@"Some silly log message %@-%@");

Исправлено

NSLog(@"Some silly log message %@-%@", someObj1, someObj2);
6 голосов
/ 01 декабря 2008

Не полный ответ, но одна конкретная ситуация, в которой я получил это, когда пытаюсь получить доступ к объекту, который «умер», потому что я пытался использовать autorelease:

netObjectDefinedInMyHeader = [[[MyNetObject alloc] init] autorelease];

Так, например, я фактически передавал это как объект для «уведомления» (зарегистрировал его как слушателя, наблюдателя, независимо от того, что вы любите), но он уже умер, как только уведомление было отправлено, и я получил EXC_BAD_ACCESS , Изменение этого значения на [[MyNetObject alloc] init] и последующее его высвобождение по мере необходимости устраняет ошибку.

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

myObjectDefinedInHeader = aParameterObjectPassedIn;

Позже при попытке доступа к myObjectDefinedInHeader у вас могут возникнуть проблемы. Использование:

myObjectDefinedInHeader = [aParameterObjectPassedIn retain];

может быть то, что вам нужно. Конечно, это всего лишь несколько примеров того, с чем я столкнулся, и есть другие причины, но они могут оказаться неуловимыми, поэтому я упомяну их. Удачи!

6 голосов
/ 20 октября 2010

Видеоролики WWDC 2010 года доступны для всех участников программы Apple для разработчиков. Есть отличное видео: «Сессия 311 - Расширенный анализ памяти с помощью инструментов», в котором показаны некоторые примеры использования зомби в инструментах и ​​устранения других проблем с памятью.

Для ссылки на страницу входа нажмите ЗДЕСЬ .

5 голосов
/ 26 декабря 2012

Другим методом перехвата исключений EXC_BAD_ACCESS до их возникновения является статический анализатор в XCode 4 +.

Запустите статический анализатор, выбрав Product> Analyze (shift + cmd + B). При нажатии на любые сообщения, сгенерированные анализатором, будет наложена диаграмма на ваш источник, показывающая последовательность удержаний / выпусков объекта, нарушившего работу.

enter image description here

5 голосов
/ 07 декабря 2009

Я считаю полезным установить точку останова на objc_exception_throw. Таким образом, отладчик должен сломаться, когда вы получите EXC_BAD_ACCESS.

Инструкции можно найти здесь Техника отладки

5 голосов
/ 23 июля 2009

Просто добавьте еще одну ситуацию, в которой это может произойти:

У меня был код:

NSMutableString *string;
[string   appendWithFormat:@"foo"];

Очевидно, я забыл выделить память для строки:

NSMutableString *string = [[NSMutableString alloc] init];
[string   appendWithFormat:@"foo"];

исправляет проблему.

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