Перерыв в EXC_BAD_ACCESS в XCode?
-
06-07-2019 - |
Вопрос
Я новичок в разработке iPhone и XCode в целом и понятия не имею, с чего начать устранение неполадок EXC_BAD_ACCESS
сигнал.Как я могу заставить XCode прерваться именно на той строке, которая вызывает ошибку?
Кажется, я не могу заставить XCode остановиться на строке, вызывающей проблему, но я вижу следующие строки в моей консоли отладки:
Вс 25 октября 15:12:14 jasonsmacbook Тестовый проект [1289] :Cgcontextset strokecolorwithcolor:недопустимый контекст
Вс 25 октября 15:12:14 jasonsmacbook Тестовый проект [1289] :Ширина cgcontextset lineWidth:недопустимый контекст
Вс 25 октября 15:12:14 jasonsmacbook Тестовый проект [1289] :Путь CGContextAddPath:недопустимый контекст
Вс 25 октября 15:12:14 jasonsmacbook Тестовый проект [1289] :CGContextDrawPath CGContextDrawPath:недопустимый контекст
2009-10-25 15:12:14.680 LanderTest[1289:207] *** -[ CFArray objectAtIndex:]:сообщение отправлено в освобожденный экземпляр 0x3c4e610
Теперь я пытаюсь обратиться к контексту, который я извлекаю из UIGraphicsGetCurrentContext()
и переходим к объекту, с помощью которого я хочу рисовать.
Дальнейшая отладка методом проб и ошибок, и я обнаружил, что NSMutableArray
У меня есть свойство, потому что в моем классе был зомби.Я зашел в init
функция для класса, и вот код, который я использовал:
if ((self = [super init])) {
NSMutableArray *array = [NSMutableArray array];
self.terrainBlocks = array;
[array release];
}
return self;
}
Я удалил [array release]
линия, и это больше не дает мне возможности EXC_BAD_ACCESS
сигнал, но теперь я не понимаю, почему это работает.Я думал, что когда я использую это свойство, оно автоматически сохраняет его для меня, и, таким образом, я должен освободить его изнутри init
чтобы у меня не было утечки информации.Я совершенно запутался в том, как это работает, и все руководства и вопросы Stackoverflow, которые я прочитал, только еще больше запутывают меня в том, как задавать свойства в моем методе инициализации.Похоже, нет единого мнения относительно того, какой способ является лучшим.
Решение
В случае любых ошибок EXC_BAD_ACCESS вы обычно пытаетесь отправить сообщение освобожденному объекту. ЛУЧШИЙ способ отследить это - использовать NSZombieEnabled . р>
Это работает, фактически не выпуская объект, а заключая его в "зомби" и установив флаг внутри него, который говорит, что обычно он был бы выпущен. Таким образом, если вы попытаетесь получить к нему доступ снова, он все еще будет знать, что было до того, как совершил ошибку, и с помощью этой небольшой информации вы обычно можете вернуться назад, чтобы увидеть, в чем заключалась проблема.
Это особенно помогает в фоновых потоках, когда отладчику иногда не хватает полезной информации.
ОЧЕНЬ ВАЖНО ЗАМЕЧАТЬ , однако, вам нужно на 100% убедиться, что это только в вашем отладочном коде, а не в коде дистрибутива. Поскольку ничего не выпущено, ваше приложение будет течь и течь и течь. Чтобы напомнить мне сделать это, я поместил этот журнал в моем appdelegate:
if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
Если вам нужна помощь в поиске точной строки, выполните Build-and-Debug ( CMD-Y ) вместо Build-and-Run ( CMD-R ). ). Когда приложение падает, отладчик покажет вам, какая именно строка и в сочетании с NSZombieEnabled, вы сможете узнать, почему именно.
Другие советы
О вашем массиве. Линия
NSMutableArray *array = [NSMutableArray array];
фактически не дает вам сохраненный объект, а скорее объект автоматического выпуска. Вероятно, он будет сохранен в следующей строке, но тогда вы не должны выпускать его в третьей строке. Просмотрите этот
Это фундаментальное правило:
Вы становитесь владельцем объекта, если создаете его с помощью метода, имя которого начинается с & # 8220; alloc & # 8221; или & # 8220; новый & # 8221; или содержит & # 8220; копию & # 8221; (например, alloc, newObject или mutableCopy), или если вы отправите ему сообщение сохранения. Вы несете ответственность за отказ от владения принадлежащими вам объектами с помощью выпуска или автоматического выпуска. В любое другое время, когда вы получаете объект, вы не должны отпускать его.
В Xcode 4 вы можете включить зомби, щелкнув раскрывающийся список Схема (вверху слева, справа рядом с кнопкой остановки) - > Изменить схему - > Вкладка «Диагностика» - > Включить объекты зомби
Xcode / gdb всегда прерывается на EXC_BAD_ACCESS
, вам просто нужно пройтись по стеку вызовов, чтобы найти код, который его вызвал. Р>
Обратите внимание, что такого рода ошибки часто возникают с объектами autoreleased
, что означает, что основной причиной проблемы не будет стек вызовов, вызвавший EXC_BAD_ACCESS
. Именно тогда стали полезными NSZombieEnabled и NSAutoreleaseFreedObjectCheckEnabled.
Новый ответ на старую ветку ... в XCode 4 наиболее эффективный способ диагностики исключений EXC_BAD_ACCESS - это использование инструментов для профилирования вашего приложения (в XCode нажмите Product / Profile и выберите Zombies). Это поможет вам идентифицировать сообщения, отправленные на освобожденные объекты.
Из классов Stanford CS193P: если вы добавите точку останова (вручную, путем редактирования точек останова) для символа objc_exception_throw
, вы сможете получить гораздо более четкое представление о том, что пошло не так - позволяя вещам перейти к точке когда отладчик останавливается сам по себе, он, как правило, запутывает вещи и портит трассировку стека. Когда вы останавливаетесь в objc_exception_throw, вы часто можете вспомнить, какой именно доступ / операция вызвали вашу проблему.
Еще один полезный подход - установка точек останова, которые будут срабатывать сразу после возникновения исключения:
Откройте окно точек останова (Запустите & # 8211; Показать & # 8211; точки останова) и добавьте две символические точки останова под названием & # 8220; objc_exception_throw & # 8221; и & # 8200; [повышение NSException] " Р>
От: http://blog.emmerinc.be/index.php/2009/03/19/break-on-exception-in-xcode/
Просто хотел добавить для других, кто приходит из Интернета, ища решения для той же ошибки, но с другой ошибкой.В моем случае я получил ту же ошибку, когда попытался создать экземпляр NSDictionary с опечаткой в имени ключа, где я забыл добавить "@" перед своим ключом:
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys: myObj1, @"goodKey", myObj2, "badkey @ is missing in front", nil];
Я надеюсь, что не пропустил идентичный ответ, но я обнаружил, что некоторые проекты могут выдать эту ошибку из-за запуска на симуляторах для более старых версий iOS, которые могут быть несовместимы с зависимостью или структурой проекта. Я слишком долго гнался за одним из них, прежде чем понял, что это просто происходит в версиях -older-simulator, таких как iPhone 4S, приложение даже не должно было пытаться поддерживать.
Было бы неплохо получить более подробное сообщение об ошибке, но я полагаю, что это ответственность структуры, в которой она возникла ... Во всяком случае, это довольно распространенная поисковая система, и, возможно, это поможет кому-то дурачиться так плохо, как я нашел себя.
Перед включением зомби я рекомендую сначала избавиться от всех предупреждений (если они есть). Простые вещи, такие как не пустая функция без return
, могут вызвать эту ошибку. Если у вас нет предупреждений, продолжайте, как предлагают другие ответы.