Статический анализатор Xcode 4 сообщает в моем коде о некоторых ложных срабатываниях. Есть ли способ их подавить?
Можно ли подавить предупреждения статического анализатора Xcode 4?
Ответы (4)
Я нашел решение: ложных срабатываний (например, шаблона проектирования Apple singleton) можно избежать с помощью:
#ifndef __clang_analyzer__
// Code not to be analyzed
#endif
Анализатор не будет анализировать код между этими директивами препроцессора.
__clang_analyzer__
— это макрос, определяемый при компиляции программы для анализатора (см. Руководство пользователя Clang а>). Когда он определен, код между #ifndef
и #endif
не компилируется, а значит анализатор его не видит. Однако когда программа не компилируется для анализатора, макрос не определяется и код компилируется как обычно.
- person DreamOfMirrors; 29.07.2015
Взгляните на эту страницу, которая показывает, как использовать несколько #define для аннотирования методов и параметров Objective-C, чтобы помочь статическому анализатору (clang) делать правильные вещи.
http://clang-analyzer.llvm.org/annotations.html
С этой страницы:
Внешний интерфейс Clang поддерживает несколько аннотаций на уровне исходного кода в виде атрибутов и прагм в стиле GCC, которые могут сделать использование Clang Static Analyzer более полезным. Эти аннотации могут помочь подавить ложные срабатывания, а также повысить способность анализатора находить ошибки.
#ifndef __clang_analyzer__
, поскольку они применяются к методам, где бы они ни использовались. Например: @property (nonatomic, retain) NSString* newString NS_RETURNS_NOT_RETAINED;
- person Noah Harrison; 01.12.2012
См. мой ответ >здесь. Вы можете добавить к файлам флаг компиляции, и статический анализатор их проигнорирует. Это, вероятно, лучше для стороннего кода, о котором вы не беспокоитесь, а не для собственного кода, который вы пишете.
в большинстве случаев использование таких вещей, как CF_RETURNS_RETAINED и соблюдение правила «создать», работает для меня, но я столкнулся с случаем, который я не мог НЕ подавить. Наконец нашел способ подавить анализатор, посмотрев исходный код llvm:
https://llvm.org/svn/llvm-project/cfe/trunk/test/ARCMT/objcmt-arc-cf-annotations.m.result
«Проверьте, подавляем ли мы ошибку при сохранении указателя на глобальную переменную».
static CGLayerRef sSuppressStaticAnalyzer;
static CGLayerRef sDmxImg[2][2][1000]; // a cache of quartz drawings.
CGLayerRef CachedDmxImg(...) // which lives for lifetime of app!
{
...
CGLayerRef img = sDmxImg[isDefault][leadingZeroes][dmxVal];
if ( !img )
{
NSRect imgRect = <some cool rectangle>;
[NSGraphicsContext saveGraphicsState];
CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
CGLayerRef cgLayerRef = CGLayerCreateWithContext(ctx, imgRect.size, NULL);
CGContextRef layerCtx = CGLayerGetContext(cgLayerRef);
[NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithGraphicsPort:layerCtx flipped:YES]];
... draw some gorgeous expensive Quartz stuff ...
img = cgLayerRef;
sDmxImg[isDefault][leadingZeroes][dmxVal] = cgLayerRef;
sSuppressStaticAnalyzer = cgLayerRef; // suppress static analyzer warning!
[NSGraphicsContext restoreGraphicsState];
}
return img;
}
По какой-то причине назначение статическому массиву не подавило предупреждение, но назначение простому старому статическому массиву 'sSuppressStaticAnalyzer' подавило. Кстати, описанный выше метод с использованием CGLayerRef — это самый быстрый из найденных мной способов перерисовки кэшированных изображений (помимо OpenGL).