Как может я фиксировать этот лязг, предупреждающий: “Объект с +0 сохраняет количества, возвращенные вызывающей стороне, где +1 (владение) сохраняют количество, ожидается”?

У меня есть часть кода Objective C, который похож на следующее:

- (NSString *)copyData:(NSData *)data
{
    NSString *path = [[[self outputDirectory] stringByAppendingPathComponent:@"archive"] stringByAppendingPathExtension:@"zip"];
    NSLog(@"Copying data to %@", path);
    [data writeToFile:path atomically:NO];
    return path;
}

Код называют от инициализатора, который похож на это:

- (id)initWithData:(NSData *)data
{
    if ((self = [super init]) != nil) {
        NSString *path = [self copyData:data];        // Line 41 (referenced in warning, shown below)
        return [self initWithContentsOfFile:path];
    }
    return self;
}

При выполнении лязга статический анализатор я получаю соблюдающие предупреждения для path переменная:

Потенциальная утечка объекта, выделенного на строке 41 и сохраненный в 'путь'

Объект с +0 сохраняет количества, возвращенные вызывающей стороне, где +1 (владение) сохраняют количество, ожидается

Я смущен. Мое понимание - это stringByAppendingPathComponent должен возвратить автовыпущенную строку, таким образом, она должна иметь сеть, сохраняют количество 0. (Очевидно, я не хочу сохранять его.)

Я попытался измениться copyData: для возврата следующего но это не избавилось от предупреждения:

return [[path retain] autorelease];

Таким образом, каково соглашение с этим предупреждением?

10
задан mipadi 14 May 2010 в 22:23
поделиться

4 ответа

Я подозреваю, что он просто замечает метод с префиксом copy и отмечает его как что-то, что должно возвращать что-то, чем владеет вызывающая сторона, потому что он думает, что следует соглашениям Cocoa об именовании.

В вашем случае, конечно, вы ссылаетесь на файлы и тому подобное, поэтому это предупреждение игнорируется. Если вы измените имя вашего метода на что-то вроде saveData: вместо этого, я готов поспорить, что предупреждение исчезнет.

15
ответ дан 3 December 2019 в 14:43
поделиться

Поскольку у метода есть имя copy , анализатор ожидает, что возвращаемый объект будет иметь счетчик удержания +1, согласно Руководство по управлению памятью .

4
ответ дан 3 December 2019 в 14:43
поделиться

Нет, это неверно; если метод не содержит "alloc", "copy", "new" или одно из других ключевых слов, подразумевающих, что объект будет принадлежать вызывающему, метод возвращает автоматически освобожденный или иным образом управляемый объект, поэтому stringByAppendingPathComponent возвращает автоматически освобожденную строку.

Кроме того, ваш метод "copyData" содержит слово "copy", подразумевая, что результат должен принадлежать (и освобождаться) вызывающей стороне. Однако результат, который вы вернули, был автоматически освобожден, отсюда и сообщение об ошибке, которое он вам выдает. Если вы хотите исправить ошибку, не выполняйте автоотдачу. То есть:

 return [path retain]

Конечно, это подразумевает, что вызывающие вашу функцию должны освободить ее. В качестве альтернативы вы можете изменить имя вашей функции так, чтобы оно соответствовало рекомендациям по управлению памятью.

Название "copyData", IMHO, в любом случае неинтуитивно понятно. Я бы предложил переименовать вашу функцию в "pathToSavedDataWithData" или что-то подобное. Что-то, что говорит о том, что она на самом деле делает.

4
ответ дан 3 December 2019 в 14:43
поделиться

Кроме того, в тех случаях, когда вы действительно хотите назвать метод «копией» или чем-то еще, потому что, независимо от руководящих принципов управления памятью Какао, копия - лучшее имя для метода, вы можете аннотировать объявление метода с помощью NS_RETURNS_NOT_RETAINED , и тогда Clang не выдаст вам предупреждения. Итак:

// Copies data from data to string; does not follow the copy rule
- (NSString*)copyData:(NSData*)data NS_RETURNS_NOT_RETAINED;
9
ответ дан 3 December 2019 в 14:43
поделиться