EXC_BAD_ACCESS при установке ivars напрямую (без использования методов доступа) внутри метода -init, почему? - PullRequest
2 голосов
/ 13 сентября 2010

Я потратил около 10 часов, пытаясь найти эту ошибку, которая вызывала сбой моего приложения, и это было в последнем месте, где я выглядел (ну, это было бы, но последнее место, где я когда-либо ожидал).

Изначально я думал, что у меня проблемы с управлением памятью (несбалансированное сохранение / освобождение), потому что сбой происходил каждый раз, когда я отправлял -removeAllObjects на NSMutableArray, заполненный моими объектами.Авария не произойдет, когда в первый раз позвонят -removeAllObjects.Я мог бы очистить массив один раз, снова заполнить его, а затем на втором очистить, я получил бы EXC_BAD_ACCESS.Это когда мой массив заполняется 3 объектами в первом «цикле» и 3 снова во втором «цикле».Когда я хранил только 1 объект в массиве в каждом цикле, потребовалось 4 цикла сбоя (при 4-м вызове -removeAllObjects).

Я НАКОНЕЦ понял, что сбой исчезнет, ​​если я изменю -init метод моего пользовательского объекта.Вот реализация -init;все 4 ивара являются синтезированными свойствами с (nonatomic, retain), все с типом (NSString *) за исключением icon, который является (NSNUmber *)

-(id)init {
    if (self = [super init]) {
        ip = @"";
        mac = @"";
        vendor = @"";
        icon = [NSNumber numberWithInt:0];
    }
    return self;
}

Изменение этого исправило ошибку:

-(id)init {
    if (self = [super init]) {
        self.ip = @"";
        self.mac = @"";
        self.vendor = @"";
        self.icon = [NSNumber numberWithInt:0];
    }
    return self;
}

Я читал, что нельзя использовать методы доступа в методе -init, потому что это может вызвать проблемы (например, с подклассами).

Если кто-то может объяснить мне, почему моя ошибка исчезаеткогда я использую аксессуары, я был бы невероятно благодарен!Серьезно, это сводило меня с ума, было до 5 утра прошлой ночью из-за этого.

1 Ответ

9 голосов
/ 13 сентября 2010

Вы присваиваете, но не сохраняете, переменные экземпляра напрямую.Когда вы используете точечный синтаксис, вы запускаете часть retain синтезированного свойства и, таким образом, сохраняете их.

-(id)init {
    if (self = [super init]) {
        ip = @"";
        mac = @"";
        vendor = @"";
        icon = [[NSNumber numberWithInt:0] retain];
    }
    return self;
}

Это, вероятно, должно решить проблему (хотя я немного удивленЯ думал, что 10 все еще находится в кэше экземпляров NSNumber. Возможно, нет.).

Технически вы должны также сохранить строки @ "", но вы можете избежать этого, потому что такие строки являются специальной константой в регистрестрока, которая выходит из скомпилированного исполняемого файла (в качестве частного подкласса NSString, который переопределяет отсутствие ответа на retain / release / autorelease).

Руководство по управлению памятью подробно описывает это.Для тех, кто плохо знаком с платформой, я бы предложил перечитывать ее раз в месяц (нет, на самом деле - чередование кода с периодическим перечитыванием документации часто выявляет тонкие детали, которых у вас не хватало опытараньше. I все еще перечитайте основные руководства на полугодовой основе.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...