Несмотря на то, что наш анализатор позиционирует себя как одно из наиболее простых средств в установке и повседневном использовании (всё работает "из коробки" и не требует никакой особенной настройки), некоторым пользователям иногда недостаёт гибкости отдельных диагностик. К сожалению, простота использования и гибкость настроек - требования если уж не противоположные по своему духу, то иногда несколько конфликтующие друг с другом. В данной заметке речь пойдёт о дополнительном механизме настройки некоторых диагностик, который может пригодиться некоторым из наших уважаемых пользователей.
Ранее уже можно было управлять некоторыми диагностиками с помощью специальных комментариев. Про них можно узнать из описания диагностик в документации. Например, см. комментарий //-V610_LEFT_SIGN_OFF для диагностики V610.
Но все эти настройки касались подавления ложных срабатываний. Теперь же появились настройки, наоборот позволяющие пользователям подсказать анализатору, где он ещё может найти ту или иную ошибку.
Общий синтаксис нового механизма следующий: для того, чтобы активировать некоторое дополнительное правило, требуется использовать комментарий //+V. Мы выбрали такую форму из-за того, что она похожа на уже широко использующейся комментарий для подавления ложных срабатываний: //-V. Формат добавления нового правила для некоторой диагностики довольно прост:
//+V<Номер диагностики>, <Ключ>:<Значение>, ... , <Ключ>:<Значение>
Параметры в диагностике могут находиться в каком угодно порядке относительно друг друга. В некоторых диагностиках может иметь место возможность добавлять несколько параметров с одинаковым ключом, но разными значениями. В некоторых диагностиках возможно отсутствие того или иного параметра.
Настройки диагностик могут быть записаны:
Ограничение - правило должно быть записано в одну строчку.
Примеры:
//+V128,function:N128_write_it,non_memsize:2,class:N128_T
//+V576,function:foo,format_arg:1,ellipsis_arg:3,namespace:X,class:Y
На момент написания статьи новые настройки реализованы для двух диагностик: V128 и V576. В дальнейшем, могут появиться новые настройки для других диагностик.
Диагностика V128 предназначена для поиска в коде мест, где переменная memsize-типа записывается в файл или считывается из файла. Полное описание диагностики можно прочесть по ссылке, а здесь будет рассказано про её новую настройку. Один из пользователей попросил расширить диагностику V128 путём добавления возможности выдачи предупреждения на пользовательские функции.
Формат расширения следующий: возле прототипа функции (или возле её реализации, или в общем заголовочном файле) пишется комментарий специального вида. Начнём с примера использования:
//+V128, function:write, non_memsize:2
void write(string name, char);
void write(string name, int32);
void write(string name, int64);
foo()
{
write("zz", array.size()); // warning V128
}
Формат:
Уровень диагностики в случае срабатывания на пользовательской функции - всегда первый.
Напоследок дадим наиболее полный пример использования:
//Предупреждать, когда в метод C класса B
//из пространства имён A во второй или третий
//аргумент была помещена переменная типа memsize
//+V128,namespace:A,class:B,function:C,non_memsize:3,non_memsize:2
Диагностика V576 предназначена для поиска несоответствия аргументов функций наподобие printf() их форматной строке. Потенциальный пользователей попросил расширить эту диагностику на случай собственных функций. Нужно, чтобы анализатор выдавал предупреждения на случай, если в некотором месте в функцию помещён аргумент, несоответствующий форматной строке. Подразумевается, что принцип форматирования строк совпадает с функцией printf().
Опять же, сказано - сделано.
Формат расширения аналогичен формату настройки диагностики V128. Возле прототипа функции (или возле её реализации, или в общем заголовочном файле) пишется комментарий специального вида. Начнём, опять же, с примера использования:
//+V576, function:Mylog, format_arg:1, ellipsis_arg:2
Mylog("%f", time(NULL)); // warning V576
Формат:
Напоследок, дадим наиболее полный пример использования:
//Предупреждать, когда в методе C класса B
//из пространства имён A аргументы, начиная с
//третьего, не совпадают с типом, заданным в
//форматной строке второго аргумента.
//+V576,namespace:A,class:B,function:C,format_arg:2,ellipsis_arg:3
Наш инструмент постоянно развивается, в него постоянно добавляются новые возможности и прочие "вкусности". Надеюсь, мы показали, что любим наших клиентов и ценим их пожелания. Приобретая лицензию на PVS-Studio, вы получите качественную поддержку и реализацию функционала, который поможет получить максимум пользы от статического анализа кода.