Вопрос

Я новичок в разработке 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 , могут вызвать эту ошибку. Если у вас нет предупреждений, продолжайте, как предлагают другие ответы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top