Как объяснить Clang статический анализатор, когда что-то не протекает? - PullRequest
2 голосов
/ 22 июля 2011

При использовании статического анализатора Clang для анализа моего кода Objective-C для iOS я получаю много «потенциальных утечек». Многие утечки заставляют меня задуматься, почему это вообще ошибочно. В частности, меня особенно поразил один пример:

У меня есть переменная класса типа NSDictionary, используемая для хранения некоторых настроек. Теперь, когда у меня есть способ изменить что-то внутри словаря:

- (void) loadPassengerCompartiments {
    NSMutableArray *paxCompartiments = [self.outputTable objectAtIndex:2];
    NSArray *paxCompSrc = [self.values objectForKey:@"PassengerCompartiments"];

    for(MassPerson *passenger in paxCompSrc) {
=>      [paxCompartiments addObject:[[PaxCompartimentOutputField alloc] initWithPerson:passenger]];
    }
}

Лежит при линейном распределении и прямой ассоциации PaxCompartimentOutputField. При запуске этого кода в инструментах он не протекает.

Два способа, которыми я мог придумать, чтобы решить это:

  1. использование autorelease
  2. заменить встроенное распределение следующим кодом:

(код)

PaxCompartimentOutputField *field = [[PaxCompartimentOutputField alloc] initWithPerson:passenger];
[paxCompartiments addObject:field];
[field release];

Первый вариант устарел imho (и особенно на iOS его использование не рекомендуется) Второй вариант довольно громоздкий - особенно при создании массива с большим количеством объектов (например, 10 объектов загружают настройки по умолчанию).

Я не хочу игнорировать предупреждения Clang, так как это отличный инструмент для поиска ошибок и утечек. Каков «правильный» способ сделать это в Objective-C для этих случаев?

Ответы [ 2 ]

8 голосов
/ 22 июля 2011

Это утечка.

Поскольку вы выделяете init_100 *, вы владеете им, и вы должны отказаться от владения им.

У вас есть 3 варианта(вы уже упомянули 2 из них):

1) Используйте удобный конструктор , если он доступен, или в пользовательском классе объявите его.Удобные конструкторы возвращают объекты , которым вы не владеете , обычно отправляя сообщение autorelease объекту, который они возвращают.Выглядело бы это так:

[paxCompartiments addObject:[PaxCompartimentOutputField paxCompartimentOutputWithPerson:passenger]];

2) Использовать autorelease.

[paxCompartiments addObject:[[[PaxCompartimentOutputField alloc] initWithPerson:passenger]] autorelease];

3) Использовать временную переменную.

PaxCompartimentOutputField *tempField = [[PaxCompartimentOutputField alloc] initWithPerson:passenger];
[paxCompartiments addObject:tempField];
[tempField release];
2 голосов
/ 22 июля 2011

Существует список исходных аннотаций , которые вы можете использовать с Clang.

Это может помочь.

...