Любая возможная причина, по которой переменная isa сбрасывается на ноль?

Мое приложение для iPhone продолжает получать ошибку BAD_EXC_ACCESS после некоторого времени работы, после мучительной отладки я обнаружил, что одна из моих статических переменных (точнее, NSPredicate) была повреждена: она все еще указывала на исходный адрес, но ее переменная isa была сброшена на 0!

Это полностью бьет меня, как получилось, что переменная isa была сброшена на 0 ?! Любая идея ?

Спасибо!

Обновление: опубликуйте код. На самом деле код взят из ABContactHelper от erica. Я немного изменил его, чтобы использовать шаблоны предикатов, чтобы сделать запрос более эффективным, поэтому я добавил эту функцию:

+ (NSPredicate*) predicateforMatchingName:(NSString*) name {
        //templateForMatchingName is a static variable I declare elsewhere
        //static NSPredicate * templateForMatchingName =nil;
    if (templateForMatchingName == nil) {
        templateForMatchingName = [NSPredicate predicateWithFormat:@"firstname contains[cd] $NAME1 OR lastname contains[cd] $NAME2 OR nickname contains[cd] $NAME3 OR middlename contains[cd] $NAME4"];
    }

    NSDictionary *sub = [NSDictionary dictionaryWithObjectsAndKeys:
                         name,@"NAME1",
                         name,@"NAME2",
                         name,@"NAME3",
                         name,@"NAME4",
                         nil];

    NSPredicate *pred = [templateForMatchingName predicateWithSubstitutionVariables:sub];
    return pred;
} 

Я думал, что этот код совершенно «нормальный», templateForMatchingName невозможно изменить после его создания. Но затем я обнаружил, что его переменная isa была сброшена. Он не обязательно равен нулю. На этот раз я обнаружил, что он был сброшен на другое значение. И странно то, что он по-прежнему указывал на исходную область.

Любая идея?


person Qiulang    schedule 20.10.2011    source источник
comment
BAD_EXC_ACCESS — обычно означает, что вы пытаетесь использовать освобожденный объект. разместите свой плохой код здесь   -  person    schedule 20.10.2011


Ответы (3)


Вы вызываете метод класса, который возвращает автоматически выпущенный объект; попробуйте добавить вложенное сохранение во время создания экземпляра или просто используйте alloc&init.

И да, указатель будет указывать на исходный адрес, поэтому он выдает это исключение. Если указатель был установлен на nil, он снова создал бы экземпляр вашего объекта из-за оператора if.

person NJones    schedule 21.10.2011

Вероятно, в какой-то момент объект был освобожден, и его память повторно использовалась. Попробуйте это с инструментом Зомби и посмотрите. И теперь, когда вы разместили свой код, я вижу, что это действительно так. Метод predicateWithFormat: возвращает экземпляр, которым вы не владеете, который может быть выпущен после истечения срока службы текущего пула автовыпуска. Вам нужно сохранить его, если вы хотите сохранить его (и освободить объект, если вы переназначите переменную).

person Chuck    schedule 20.10.2011
comment
Это статическая переменная. И он по-прежнему указывал на исходный адрес, просто его ias был сброшен. У меня закончился раствор :( - person Qiulang; 21.10.2011
comment
@Qiulang: Ничто из того, что вы сказали, не имеет никакого отношения к освобождаемому объекту. Статические переменные обычно не делают вещи, на которые они указывают, бессмертными, а освобождаемый объект не приводит к тому, что указатели на этот адрес переназначаются на новый адрес. - person Chuck; 21.10.2011
comment
@Qiulang Вы должны были попробовать это; Код, который вы разместили, имеет проблему с памятью, которую поймали бы зомби. (+1 за оба ответа) - person justin; 21.10.2011
comment
@NJones: Не беспокойтесь. Я думаю, что мы оба написали примерно в одно и то же время, и в любом случае нет ничего плохого в том, чтобы сказать то же самое от кого-то другого. - person Chuck; 21.10.2011
comment
ОП, ваш первый комментарий к этому ответу показывает ваше замешательство. Статическая переменная просто означает переменную класса. Так что да, класс должен иметь переменную с именем temp.. И вы оставили этот указатель, указывающий на адрес temp... Даже после того, как сохраненный вами автоматически выпущенный объект был освобожден, потому что вы его не сохранили. Вот почему, когда вы смотрели на то, где находилась ISA объекта, вы получали то, что считали мусором, но на самом деле это было то, что жило там сейчас. - person NJones; 21.10.2011

Спасибо парень! Это именно причина; после того, как я сохранил свой объект, проблема была решена. Я думаю, что запутался со статической переменной и базовыми данными, на которые она указывает.

Кстати, для тех, кто может быть заинтересован в этой проблеме, вы также можете обратиться к этому, Зачем сохранять статическую переменную?

Еще один урок, извлеченный здесь, заключается в том, что всякий раз, когда переменная isa сбрасывается, это означает, что память, в которой находится объектный процесс, была восстановлена.

person Qiulang    schedule 21.10.2011