Как объекты проверки времени компиляции передаются конструктору NSArray для nil

59
7

NSArray скорее не нравится, когда передается объект nil как часть его конструктора:

UIView *aView;
UIView *aSecondView = [[UIView alloc] init];
NSArray *array = @[aView, aSecondView];

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

Имеет ли clang какие-либо средства, чтобы попытаться обнаружить такую ошибку? Для некоторых тривиальных случаев (например, выше: локальная переменная, не привязанная к стеку), похоже, что проблема статического анализатора ударила из парка.

спросил(а) 2014-07-12T00:43:00+04:00 5 лет, 6 месяцев назад
2
Решение
48

TL; DR: -Wuninitialized ловит этот конкретный пример, __attribute__((nonnull)) для параметров для функций/методов поможет поймать nil качестве аргумента в целом.

Для этого конкретного примера (переменная, специально не инициализированная), вы можете использовать -Wuninitialized чтобы поймать их:

○ xcrun clang a.m -F/System/Library/Frameworks -c -o a.o -Wuninitialized
a.m:6:22: warning: variable 'aView' is uninitialized when used here [-Wuninitialized]
NSArray *array = @[aView, aSecondView];
^~~~~
a.m:4:16: note: initialize the variable 'aView' to silence this warning
NSView *aView;// = nil;
^
= nil
1 warning generated.

Для передачи nullptr/NULL/nil в функции/методы __attribute__((nonnull)) должен работать в большинстве случаев. Поскольку это API, предоставляемый Apple, вам нужно будет подать радар и надеяться, что они его добавят.

PS: На самом деле, __attribute__((nonnull)) не будет "просто работать", в этом случае (если вы, например, инициализировали aView для nil. Последовательность @[...], похоже, создает массив и вызывает +[NSArray arrayWithObjects: count:], где вы могли бы пометить первый аргумент как nonnull, но не тот, на который это указывает. В любом случае, должно быть относительно просто написать пропуск clang для упомянутого вами анализа. Вы должны подать радар, так как такой проход может избежать больших потерь времени.

PPS: Кажется, __attribute__((nonnull)) не распространяет много информации, что печально. :-( Если у вас есть функция f(type arg __attribute__((nonnull))) и вы передадите ей переменную, которую вы инициализировали nil и никогда не касались снова, она не предупреждает.

ответил(а) 2014-07-12T02:08:00+04:00 5 лет, 6 месяцев назад
Еще 1 ответ
47

Я считаю, что вы правы, статический анализатор Clang ударил эту ошибку из парка. Он встроен в Xcode (6 бета, как я тестировал). Go Building Settings > Статический анализатор - Политика анализа> Установите анализ во время сборки на Yes. Чтобы выполнить ручную работу, перейдите Product> Analyze.

enter image description here

Статический анализатор также может использоваться как автономный инструмент в командной строке. Другим вариантом анализа во время компиляции является добавление сценария запуска на этапах сборки до компиляции источников.

ответил(а) 2014-07-12T02:45:00+04:00 5 лет, 6 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема