Метод init и «Объект с +0 счетом удержания возвращается вызывающей стороне, где ожидается удержание +1 (владелец)» - ложно-положительный? - PullRequest
1 голос
/ 26 марта 2012

Прежде всего: я понимаю, почему это предупреждение существует, я просто не могу объяснить, почему оно срабатывает в этих обстоятельствах.Официальная политика управления памятью Какао такова: «Вы владеете любым создаваемым вами объектом. Вы создаете объект, используя метод, имя которого начинается с« alloc »,« new »,« copy »или« mutableCopy »(например, alloc,newObject или mutableCopy).

Вы можете вступить во владение объектом, используя команду retain "

Я знаю, есть такой код:

- (id) foo
{
    // do something
    return self;
}

- (id) init
{
    self = [super init];
    return [self foo]; // clang static analyzer is complaining about returning an object with a +0 retain count here, although a +1 would be expected
}

Afaik, это ложное срабатываниеиз лязга, не так ли?Я имею в виду, что единственными методами, которые увеличивают количество записей, являются «retain» и все методы, имена которых начинаются с «alloc», «new», «copy» или «mutableCopy», поэтому «init» не увеличиваетсяretain-count, но пересылается вызывающей стороне для передачи возвращаемого значения метода «alloc» класса, так что фактически «init», как ожидается, вернет +0 retain count, а не +1, isnне так ли?Он просто возвращает объект с тем же счетом сохранения, с которым он был передан. Теперь вызов «foo» для этого объекта также не меняет счет сохранения, поэтому этот код должен быть совершенно допустимым, и на самом деле он работает просто отлично иколичество сохраняемых значений корректно на протяжении всего срока службы программы, только статический анализатор жалуется.

Ответы [ 2 ]

4 голосов
/ 26 марта 2012

Имя метода foo по соглашению означает, что он возвращает объект, которому вызывающая сторона не принадлежит.

alloc - init*** комбинации возвращают объект, которым владеет вызывающий объект.

Похоже, что анализатор не может или не пытается заглянуть внутрь foo, чтобы увидеть, что он на самом деле делает, и не знает, что возвращаемое значение - это тот же объект, что и уже принадлежащий self.

Это не ложный позитив. Если подкласс или динамически загруженная категория переопределяют foo для возврата чего-то другого:

- (id) foo; {
    return [NSNumber numberWithInt:666];
}

тогда у вас будет утечка self и избыточный выпуск NSNumber объекта.

0 голосов
/ 26 марта 2012

Да, это ложно-положительный результат, но это плохая практика для использования при разработке класса. Вместо этого вы должны вызвать foo, а затем вернуть self, например:

-(id) init
{
    if ((self = [super init]))
    {
        [self foo];
    }

    return self;
}
...