Перерыв на EXC_BAD_ACCESS в XCode?

Я новичок в разработке iPhone и XCode в целом и понятия не имею, как начать устранение сигнала EXC_BAD_ACCESS . Как я могу заставить XCode разбиться на точную строку, вызывающую ошибку?


Я не могу заставить XCode останавливаться на строке, вызывающей проблему, но я вижу следующие строки в моей консоли отладки:

Sun Oct 25 15:12:14 jasonsmacbook TestProject [1289]: CGContextSetStrokeColorWithColor: недопустимый контекст

Sun Oct 25 15:12:14 jasonsmacbook TestProject [1289]: CGContextSetLineWidth: неверный контекст

Sun Oct 25 15:12:14 jasonsmacbook TestProject [1289]: CGContextAddPath: неверный контекст

Sun Oct 25 15:12:14 jasonsmacbook TestProject [1289]: CGContextDrawPath: недопустимый контекст

2009-10-25 15: 12: 14.680 LanderTest [1289: 207] *** – [CFArray objectAtIndex:]: сообщение отправлено на освобожденный экземпляр 0x3c4e610

Теперь я UIGraphicsGetCurrentContext() привлечь контекст, который я извлекаю из UIGraphicsGetCurrentContext() и перейти к объекту, с которым я хочу рисовать.


Дальнейшая пробная NSMutableArray и отладка ошибок, и я обнаружил, что у NSMutableArray меня есть свойство для моего classа, был зомби. Я вошел в функцию init для classа, и вот код, который я использовал:

 if ((self = [super init])) { NSMutableArray *array = [NSMutableArray array]; self.terrainBlocks = array; [array release]; } return self; } 

Я удалил строку [array release] и больше не дал мне сигнал EXC_BAD_ACCESS , но теперь я смущен тем, почему это работает. Я думал, что, когда я использовал свойство, он автоматически сохранил его для меня, и поэтому я должен освободить его изнутри init чтобы у меня не было утечки. Я полностью смущен тем, как это работает, и все направляющие и вопросы Stackoverflow, которые я прочитал, только путают меня больше о том, как установить свойства в моем методе init. Кажется, нет никакого консенсуса относительно того, какой путь является лучшим.

Для любых ошибок EXC_BAD_ACCESS вы обычно пытаетесь отправить сообщение выпущенному объекту. Лучшим способом отслеживания этого является использование NSZombieEnabled .

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

Это особенно помогает в фоновых streamах, когда отладчик иногда дергает любую полезную информацию.

ОЧЕНЬ ВАЖНО ЗАМЕЧАНИЕ, однако, что вам нужно 100% убедиться, что это только в вашем отладочном коде, а не в вашем коде распространения. Поскольку ничто никогда не выпускается, ваше приложение будет течь, течет и течет. Чтобы напомнить мне об этом, я поместил этот журнал в свой appdelegate:

 if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled")) NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!"); 

Если вам нужна помощь в поиске точной строки, сделайте сборку и отладку ( CMD-Y ) вместо Build-and-Run ( CMD-R ). Когда приложение выйдет из строя, отладчик покажет вам, в какой строке и в сочетании с NSZombieEnabled, вы должны точно выяснить, почему.

О вашем массиве. Линия

 NSMutableArray *array = [NSMutableArray array]; 

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

Это основное правило:

Вы берете на себя ответственность за объект, если его создаете, используя метод, имя которого начинается с «alloc» или «new» или содержит «copy» (например, alloc, newObject или mutableCopy), или если вы отправите ему сообщение сохранения. Вы несете ответственность за отказ от владения собственными вами объектами с помощью выпуска или авторекламы. В любое другое время, когда вы получаете объект, вы не должны его отпускать.

В Xcode 4 вы можете включить Zombies, нажав на раскрывающийся список Scheme (вверху слева, рядом с кнопкой остановки) -> Edit Scheme -> вкладка Diagnostics -> Enable Zombie Objects

Xcode / gdb всегда разбивается на EXC_BAD_ACCESS , вам просто нужно EXC_BAD_ACCESS путь вверх по стеку вызовов, чтобы найти код, который его вызвал.

Обратите внимание, что такие ошибки часто возникают с autoreleased объектами, а это означает, что конечная причина проблемы не будет в стеке вызовов, который вызвал бы EXC_BAD_ACCESS . Именно тогда NSZombieEnabled и NSAutoreleaseFreedObjectCheckEnabled становятся полезными.

Новый ответ на старый stream … в XCode 4 наиболее эффективным способом диагностики исключений EXC_BAD_ACCESS является использование инструментов для профилирования вашего приложения (из XCode нажмите «Продукт / Профиль» и выберите «Зомби»). Это поможет вам идентифицировать сообщения, отправленные на освобожденные объекты.

Из classов Stanford CS193P: если вы добавили точку останова (вручную, отредактировав контрольные точки) для символа objc_exception_throw вы можете получить гораздо лучшее представление о том, что пошло не так – позволяя всем переходить к точке, где отладчик останавливается сам по себе, имеет тенденцию скрывать вещи и испортить трассировку стека. Когда вы останавливаетесь в objc_exception_throw, вы можете часто оглядываться на то, что вызвало вашу проблему.

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

Откройте окно контрольных точек (Run – Show – Breakpoints) и добавьте две символические точки останова, называемые «objc_exception_throw» и «[NSException raise]»

От: http://blog.emmerinc.be/index.php/2009/03/19/break-on-exception-in-xcode/

Просто хотел добавить для других, которые приходят из Интернета, ища решения для одной и той же ошибки, но с другой ошибкой. В моем случае я получил ту же ошибку, когда я попытался создать NSDictionary с typo в ключевом названии, где я забыл добавить «@» перед моим ключом:

 NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys: myObj1, @"goodKey", myObj2, "badkey @ is missing in front", nil]; 

Надеюсь, я не пропустил идентичный ответ, но я обнаружил, что некоторые проекты могут выбросить эту ошибку из-за запуска на симуляторах для более старых версий iOS, которые могут быть несовместимы с зависимостью проекта или структурой. Я слишком долго гонялся за одним из них, прежде чем осознать, что это происходит только в версиях -больших симуляторов, таких как iPhone 4S, приложение даже не должно пытаться поддерживать.

Было бы неплохо получить более подробное сообщение об ошибке, но я бы предположил, что это ответственность за frameworks, в которых она возникла … Во всяком случае, это довольно обычная посылка для поиска, и, возможно, это поможет кому-то разобраться с нею как я оказался.

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

Interesting Posts

Что означает эта квадратная скобка и скобка для обозначения скобок [first1, last1)?

Извлечь ссылки из файла Sitemap (xml)

Как будет работать Mac OS X Snow Leopard?

C #: Как создать атрибут метода, запускающего событие при его вызове?

Как Thread может вернуть значение после завершения работы?

Как монтировать разделы ext2 / ext3 в Mac OS X Snow Leopard?

Управление пакетами на воздушной коробке?

Проблемы с Ruby on Rails и Rake: неинициализированная константа Rake :: DSL

Точка в алгоритме многоугольника

У нас есть class classов TimeSpan в Java

Есть ли простой способ сравнить, насколько близки два цвета друг к другу

Ноутбук не загружается после необычного статического разряда?

Windows 7 двойной монитор, при открытии приложения, как контролировать, какой монитор пользовательский интерфейс приложения будет отображаться?

Класс Android LocationClient устарел, но используется в документации

Показать дубликаты данных с awk print $ 2, $ 3, $ 4 в одной строке

Давайте будем гением компьютера.