Отключение Зомби вызывает EXC_BAD_ACCESS
Я получаю сбой в приложении со следующей трассировкой стека
Thread : Crashed: com.apple.main-thread
0 libobjc.A.dylib 0x39dfa66a objc_release + 9
1 libobjc.A.dylib 0x39dfb0d7 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 358
2 CoreFoundation 0x2f4a6c69 _CFAutoreleasePoolPop + 16
3 CoreFoundation 0x2f53c1cb __CFRunLoopRun + 1306
4 CoreFoundation 0x2f4a6f0f CFRunLoopRunSpecific + 522
5 CoreFoundation 0x2f4a6cf3 CFRunLoopRunInMode + 106
6 GraphicsServices 0x343ff663 GSEventRunModal + 138
7 UIKit 0x31df216d UIApplicationMain + 1136
8 Batted 0x0009db07 main (main.m:16)
Авария происходит, когда зомби не включены в параметрах диагностики Схемы. Однако, когда я включил его, сбой не происходит.
Я читал некоторые другие вопросы и ответы по этому поводу, и все они, кажется, советуют, что, как только это поведение будет замечено, включите зомби и запустите инструменты профиля зомби на симуляторе.
Я попробовал это, но Инструменты, кажется, не указывают на что-то не так, и приложение работает. Любой ключ к тому, что еще можно сделать здесь для устранения этой проблемы? Я использую XCode 5.1 с iOS 7.1 в симуляторе.
ОБНОВЛЕНИЕ 1
Обнаружил неправильный код, вызывающий проблему, но я все еще не уверен, почему он вызывает проблему. Я использую CoreData, и в подклассе NSManagedObject, у меня есть -
- (void)willTurnIntoFault;
{
[super willTurnIntoFault];
if ([self observationInfo])
{
BNLogInfo(@"%@ has observers:\n%@", [self objectID], [self observationInfo]);
}
}
В приведенном выше коде, [self observationInfo]
это оскорбительная линия
Когда приложение запускается, я зацикливаю некоторые объекты NSManagedObject в блоке перечисления и устанавливаю для него некоторое свойство, которое, в свою очередь, запускает willTurnIntoFault
метод. Как только блок перечисления завершается, происходит сбой.
Тайна в том, что сбой не происходит внутри этого метода, но без этого метода все работает нормально.
1 ответ
В вопросах и ответах говорится, чтобы включить зомби (или запустить под инструментом Зомби), потому что зомби часто вызывает такого рода ошибки.
Но это не единственная причина.
Ваша программа повреждает кучу. Скорее всего это перезаписывает isa
указатель (указатель класса) в некотором объекте, который находится в пуле автоматического выпуска, поэтому, когда цикл выполнения истощает пул автоматического выпуска, objc_release
пытается разыменовать фальшивку isa
указатель и вылетает.
Включение зомби может маскировать такую ошибку, потому что с зомби среда выполнения никогда не освобождает объекты. Это означает, что у вас будет куча частей кучи, которые не используются (если только вы не попытаетесь отправить сообщение зомби), поэтому они никогда не вызовут проблем, если вы их испортите.
Подобные сбои могут быть очень сложными для отладки, но есть инструмент, называемый guard malloc, который иногда помогает. В строке меню выберите "Продукт"> "Схема"> "Редактировать схему". Щелкните действие "Выполнить" в списке слева. Затем перейдите на вкладку "Диагностика". Включите опцию "Включить охрану Malloc". Затем попробуйте воспроизвести аварию. Guard malloc незамедлительно обнаружит определенные типы повреждения кучи и остановит программу по команде повреждения.