Отключение Зомби вызывает 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 незамедлительно обнаружит определенные типы повреждения кучи и остановит программу по команде повреждения.

Другие вопросы по тегам