NSError** 'Потенциальное нулевое разыменование'

Приведем следующий пример:

- (BOOL) doSomething: (NSError**) pError
{
    *pError = [NSError ....];
}

Анализатор вернет следующую ошибку:

Потенциальное нулевое разыменование. В соответствии со стандартами кодирования в разделе «Создание и возврат объектов NSError» параметр может иметь значение null.

На что было бы предложение изменить это на:

- (BOOL) doSomething: (NSError**) pError
{
    if(pError)
    {
        *pError = [NSError ....];
    }
}

Но я бы предпочел добавить ненулевой атрибут к параметру ошибки, чтобы препятствовать использованию передачи нулевого значения. Я не могу понять, как правильно привести аргументы. Может ли двойной указатель иметь ненулевой атрибут?


person Kyle    schedule 14.02.2018    source источник


Ответы (1)


Но я бы предпочел добавить ненулевой атрибут к параметру ошибки, чтобы препятствовать использованию передачи нулевого значения.

Синтаксис, который вы ищете, показан в различных ответах на переполнение стека, таких как Objective-C допустимость значений NULL для выходных параметров. Таким образом, вы можете объявить, например:

(NSError * _Nullable * _Nonnull)

... и появится желаемое предупреждение:

введите здесь описание изображения

Однако вместо этого я бы посоветовал вам просто перестать отдавать предпочтение этому. Анализатор совершенно прав насчет паттерна; вы должны слушать то, что он говорит вам.

Стандартный полный шаблон для вызова метода, который косвенно возвращает NSError, например:

NSString* path = // ... whatever;
NSStringEncoding enc = // ... whatever;
NSError* err = nil;
NSString* s =
    [NSString stringWithContentsOfFile:path encoding:enc error:&err];
if (nil == s) // oops! something went wrong...

Но допустим, я абсолютно уверен, что это сработает. Тогда законно сказать:

NSString* path = // ... whatever;
NSStringEncoding enc = // ... whatever;
NSString* s =
    [NSString stringWithContentsOfFile:path encoding:enc error:nil];

Вы не должны исключать этого; это разумно и нормально.

person matt    schedule 14.02.2018
comment
Даже это — конечно — отличный ответ, я хочу добавить, что nil не NULL. nil всегда является ссылкой на (нет) объект, а NSError** не указывает на (нет) объект. - person Amin Negm-Awad; 15.02.2018
comment
I would suggest instead, however, that you simply stop preferring that.. Спасибо, честно говоря, мне нужно было, чтобы это ударило в мою голову, и ваш комментарий сделал именно это. Я также приветствую это вместо того, чтобы просто сказать, что вы нашли время, чтобы ответить на основной вопрос (хотя я буду следовать правильному решению). - person Kyle; 15.02.2018