Полученный сигнал EXC_BAD_ACCESS

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

Program received signal: "EXC_BAD_ACCESS".

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

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

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

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

Вы встречали сигнал EXC_BAD_ACCESS раньше, и как вы с ним справились?

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

Вкратце, это объясняет, как использовать класс отладки Cocoa NSZombie и инструмент командной строки "malloc_history", чтобы найти то, к чему был обращен выделенный код в вашем коде.

Sidenote:

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

UPDATE: Теперь я использую инструменты для отладки утечек. Из Xcode 4.2 выберите "Продукт" → "Профиль" и "Когда инструменты запускаются", выберите "Зомби".

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

Я просто потратил пару часов на отслеживание EXC_BAD_ACCESS и нашел NSZombies и другие env vars, похоже, ничего не сказал мне.

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

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

Исправлено с помощью

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

Ответ 6

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

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

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

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

myObjectDefinedInHeader = aParameterObjectPassedIn;

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

myObjectDefinedInHeader = [aParameterObjectPassedIn retain];

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

Ответ 7

Видеоролики WWDC 2010 доступны для всех участников программы разработчика Apple. Там есть отличное видео: "Session 311 - Advanced Memory Analysis with Instruments", который показывает некоторые примеры использования зомби в инструментах и ​​отладки других проблем с памятью.

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

Ответ 8

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

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

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

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

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

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

Ответ 9

Еще один метод для исключения исключений EXC_BAD_ACCESS до их возникновения - это статический анализатор в XCode 4 +.

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

enter image description here

Ответ 10

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

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

Ответ 11

Используйте простое правило "если вы не выделили его или не сохранили, не отпустите".

Ответ 12

Как отладить EXC_BAD_ACCESS

Проверьте ссылку выше и сделайте то, что она говорит.... Только некоторые быстрые инструкции по использованию NSZombies

Запустите приложение и после его сбоя (должно отображаться "Прервано", а не "EXC_BAD_ACCESS"... проверьте консоль (Run > Console)... там должно появиться сообщение о том, к какому объекту, который он пытался получить.

-Бен

Ответ 13

Я отлаживал и рефакторинг кода, чтобы решить эту ошибку за последние четыре часа. Сообщение выше привело меня к проблеме:

Свойство до: startPoint = [[DataPoint alloc] init]; startPoint = [DataPointList objectAtIndex: 0];
, , , x = startPoint.x - 10;//EXC_BAD_ACCESS

Свойство после: startPoint = [[DataPoint alloc] init]; startPoint = [[DataPointList objectAtIndex: 0] сохранить];

До свидания EXC_BAD_ACCESS

Ответ 14

Надеюсь, вы выпустили "строку", когда закончите!

Ответ 15

Я забыл вернуть себя в init-Method...;)

Ответ 16

Забыл вынуть указатель non-alloc'd из dealloc. Я получал exc_bad_access в моем корневом элементе UINavigationController, но только иногда. Я предположил, что проблема была в корневом представлении, потому что она терпела крах через его viewDidAppear {}. Оказалось, что это произошло только после того, как я вынул представление с помощью плохой dealloc {} release, и это все!

"EXC_BAD_ACCESS" [Переход к процессу 330] Теперь нет памяти для программирования: небезопасно вызывать malloc

Я думал, что это проблема, когда я пытаюсь выделить... не там, где я пытался освободить не-alloc, D'oh!

Ответ 17

Это отличная нить. Вот мой опыт: я испортил ключевое слово keep/assign в объявлении свойства. Я сказал:

@property (nonatomic, assign) IBOutlet UISegmentedControl *choicesControl;
@property (nonatomic, assign) IBOutlet UISwitch *africaSwitch;
@property (nonatomic, assign) IBOutlet UISwitch *asiaSwitch;

где я должен был сказать

@property (nonatomic, retain) IBOutlet UISegmentedControl *choicesControl;
@property (nonatomic, retain) IBOutlet UISwitch *africaSwitch;
@property (nonatomic, retain) IBOutlet UISwitch *asiaSwitch;

Ответ 18

Я столкнулся с EXC_BAD_ACCESS на iPhone только при попытке выполнить метод C, включающий большой массив. Симулятор смог дать мне достаточно памяти для запуска кода, но не для устройства (массив был миллионом символов, поэтому он был чрезмерным!).

EXC_BAD_ACCESS произошел сразу после точки входа метода и довольно долго меня путал, потому что он не был рядом с объявлением массива.

Возможно, кто-то еще может извлечь выгоду из моей пары часов вытягивания волос.

Ответ 19

Вызовы NSAssert() для проверки параметров метода очень удобны для отслеживания и предотвращения передачи нил.

Ответ 20

Я отлаживал и рефакторинг кода, чтобы решить эту ошибку за последние четыре часа. Сообщение выше привело меня к проблеме:

Свойство до:

startPoint = [[DataPoint alloc] init] ;
startPoint= [DataPointList objectAtIndex: 0];
x = startPoint.x - 10; // EXC_BAD_ACCESS

Свойство после:

startPoint = [[DataPoint alloc] init] ;
startPoint = [[DataPointList objectAtIndex: 0] retain];

До свидания EXC_BAD_ACCESS

Большое вам спасибо за ваш ответ. Я весь день борюсь с этой проблемой. Ты классный!

Ответ 21

У меня была эта проблема. Для меня причина заключалась в удалении управляемого объекта CoreData и попытки его прочитать потом из другого места.

Ответ 22

Просто добавьте

Lynda.com имеет фантастический DVD под названием

Основные возможности iPhone SDK

и глава 6, Урок 3 посвящен EXEC_BAD_ACCESS и работает с Zombies.

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

Ответ 23

Чтобы проверить, что может быть ошибкой

Использовать NSZombieEnabled.

Чтобы активировать объект NSZombieEnabled в вашем приложении:

Выберите "Проект" > "Редактировать Active Executable", чтобы открыть исполняемое окно "Информация". Нажмите "Аргументы". Нажмите кнопку добавления (+) в разделе "Переменные, которые должны быть установлены в среде". Введите NSZombieEnabled в столбце Name и YES в столбце Value. Убедитесь, что выбран флажок для записи NSZombieEnabled.

Я нашел этот ответ на iPhoneSDK

Ответ 24

Я понимаю, что это было спрошено некоторое время назад, но после прочтения этой темы я нашел решение для XCode 4.2: Продукт → Изменить схему → вкладка "Диагностика" → "Включить объекты зомби"

Помогло мне найти сообщение, отправленное на освобожденный объект.

Ответ 25

Как я общаюсь с EXC_BAD_ACCESS

Иногда я чувствую, что когда выдается ошибка EXC_BAD_ACCESS, xcode покажет ошибку в классе main.m, не давая дополнительной информации о том, где произошел сбой (иногда).

В те моменты времени мы можем установить Исключительную точку останова в Xcode, чтобы при исключении поймать точку останова будет размещена и будет непосредственно инфинитировать пользователя, произошедшего в этой строке

enter image description here

Ответ 26

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

Ответ 27

XCode 4 и выше, это было сделано очень просто с инструментами. Просто запустите Zombies в инструментах. В этом руководстве объясняется это хорошо: отладка exc_bad_access ошибок xcode tools

Ответ 28

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

Ответ 29

Я получил его, потому что не использовал [self performSegueWithIdentifier:sender:] и -(void) prepareForSegue:(UIstoryboardSegue *) right

Ответ 30

Не забывайте символ @ при создании строк, обработка C-strings как NSStrings приведет к EXC_BAD_ACCESS.

Используйте это:

@"Some String"

Вместо этого:

"Some String"

PS - обычно при заполнении содержимого array большим количеством записей.