Сигнал EXC_BAD_ACCESS получен

284
задан Midhun MP 22 December 2016 в 09:14
поделиться

19 ответов

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

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

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

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

193
ответ дан Lorenzo B 23 November 2019 в 01:52
поделиться

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

2
ответ дан Ryan Townshend 23 November 2019 в 01:52
поделиться

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

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

12
ответ дан Adam Rosenfield 23 November 2019 в 01:52
поделиться

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

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

8
ответ дан Brent Royal-Gordon 23 November 2019 в 01:52
поделиться

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

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

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

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

myObjectDefinedInHeader = aParameterObjectPassedIn;

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

myObjectDefinedInHeader = [aParameterObjectPassedIn retain];

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

6
ответ дан logancautrell 23 November 2019 в 01:52
поделиться

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

Свойство до: startPoint = [[DataPoint alloc] инициализация]; startPoint = [DataPointList objectAtIndex: 0];
, , , x = startPoint.x - 10; // EXC_BAD_ACCESS

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

До свидания, EXC_BAD_ACCESS

3
ответ дан 23 November 2019 в 01:52
поделиться

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

Свойство до:

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

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

2
ответ дан 23 November 2019 в 01:52
поделиться

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

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

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

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

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

Примечание:

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

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

100
ответ дан 23 November 2019 в 01:52
поделиться

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

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

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

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

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

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

5
ответ дан 23 November 2019 в 01:52
поделиться

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

3
ответ дан 23 November 2019 в 01:52
поделиться

I just spent a couple hours tracking an EXC_BAD_ACCESS and found NSZombies and other env vars didn't seem to tell me anything.

For me, it was a stupid NSLog statement with format specifiers but no args passed.

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

Fixed by

NSLog(@"Some silly log message %@-%@", someObj1, someObj2);
7
ответ дан 23 November 2019 в 01:52
поделиться

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

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

5
ответ дан 23 November 2019 в 01:52
поделиться

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

2
ответ дан 23 November 2019 в 01:52
поделиться

Я забыл вернуть себя по инит-методу... ;)

3
ответ дан 23 November 2019 в 01:52
поделиться

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

4
ответ дан 23 November 2019 в 01:52
поделиться

Забыл вынуть указатель без распределения из dealloc . Я получал exc_bad_access в моем rootView UINavigationController, но только иногда. Я предположил, что проблема была в rootView, потому что он давал сбой на полпути через viewDidAppear {}. Оказалось, что это произошло только после того, как я открыл представление с выпуском bad dealloc {}, и все!

«EXC_BAD_ACCESS» [Переключение на процесс 330] Сейчас нет памяти для программирования: небезопасно вызывать malloc

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

3
ответ дан 23 November 2019 в 01:52
поделиться

Просто чтобы добавить

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

iPhone SDK Essential Training

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

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

2
ответ дан 23 November 2019 в 01:52
поделиться

Это отличная тема. Вот мой опыт: я напортачил с ключевым словом 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;
3
ответ дан 23 November 2019 в 01:52
поделиться

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

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

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

3
ответ дан 23 November 2019 в 01:52
поделиться