Хабрахабр

Как быстро посмотреть интересные предупреждения, которые выдает анализатор PVS-Studio для C и C++ кода?

Время от времени программисты, которые начинают знакомиться с анализатором кода PVS-Studio, спрашивают: «Есть ли список предупреждений, которые точно указывают на ошибки?» Такого списка нет по той причине, что неинтересные (ложные) предупреждения в одном проекте, в другом оказываются очень важными и полезными. Однако начать знакомство с анализатором с самых интересных предупреждений вполне можно. Давайте рассмотрим эту тему подробнее.
Беда в том, что при первых запусках программист получает, как правило, огромное количество предупреждений, в которых «тонет». Естественно, у него возникает желание для начала познакомиться с самыми интересными предупреждениями, чтобы понять, стоит ли ему вообще тратить на всё это время. Отлично, вот три простых шага, которые позволят познакомиться с самыми интересными срабатываниями.

Шаг 1

Распространённая ошибка: включить все виды предупреждений. Отключите все типы предупреждений кроме основных (GA). Это не так! Неопытным пользователям кажется, что чем больше всего включить, тем лучше. Например, включив MISRA-диагностики для обыкновенной прикладной программы, вы утоните в десятках, тысячах или сотнях тысяч сообщений типа: Есть наборы диагностик, такие как 64-битные проверки и MISRA-правила, которые следует использовать, только чётко представляя, что это такое и как с ними работать.

  • V2506. MISRA. A function should have a single point of exit at the end.
  • V2507. MISRA. The body of a loop\conditional statement should be enclosed in braces.
  • V2523. MISRA. All integer constants of unsigned type should have 'u' or 'U' suffix.

Большинство MISRA-предупреждений указывают не на ошибки, а запахи кода. Естественно, человек начинает задаваться вопросами. Как в массе всех этих предупреждений найти что-то интересное? Диагностики под какими номерами он должен смотреть? Это неправильные вопросы. Нужно просто отключить набор MISRA. Это стандарт для написания качественного кода для встраиваемых устройств. Суть стандарта: сделать код крайне простым и понятным. Не надо пытаться применить его там, где он неуместен.

Да, в стандарте MISRA есть правила, нацеленные на выявление настоящих ошибок. Примечание. Но не бойтесь отключить MISRA-стандарт. Пример: V2538 — The value of uninitialized variable should not be used. Настоящие ошибки будут всё равно найдены в рамках диагностик общего назначения (GA). Вы ничего не потеряете. Например, неинициализированная переменная будет найдена благодаря диагностике V614.

Шаг 2

С этим ничего нельзя сделать, но это не так страшно, как может показаться. Любой статический анализатор при первых запусках выдаёт ложные срабатывания и требует определённой настройки. Подробнее говорить про это не будем, так как я уже много раз писал про это, например, в этой статье: "Характеристики анализатора PVS-Studio на примере EFL Core Libraries, 10-15% ложных срабатываний". Даже простая быстрая настройка позволяет убрать большинство ложных предупреждений и начать знакомиться с уже вполне адекватным отчётом.

Макросы вообще являются основным источником ложных срабатываний, так как предупреждение появляется везде, где используется неудачно реализованный макрос. Потратьте немного времени на отключение явно неактуальных предупреждений и борьбу с ложными срабатываниями из-за макросов. Подробнее формат написания комментариев рассматривается в документации. Для подавления предупреждений в макросах, рядом с их объявлением можно разместить комментарии специального вида.

Уделите этому немного времени. Да, первоначальная настройка отнимет немного времени, но кардинально улучшит восприятие отчёта за счёт исключения отвлекающего шума. Не стесняйтесь написать и задать нам вопросы. Если есть какие-то затруднения или вопросы, мы всегда готовы помочь и подсказать как лучше настроить анализатор.

Шаг 3

И только затем смотреть 2 и 3. Начать изучать предупреждения с 1 уровня. Предупреждения 1-го уровня с большей вероятностью указывают на настоящую ошибку, чем 2. Уровни предупреждений являются ничем иным, как достоверностью предупреждения.

Можно сказать, что выбирая «смотреть 1 уровень», вы нажимаете кнопку «смотреть самые интересные ошибки».

Более подробно классификация предупреждений PVS-Studio по уровням описана в статье "Как и почему статические анализаторы борются с ложными срабатываниями".

Так почему всё-таки нет списка?

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

Предупреждение выявляет потенциальную ошибку, связанную с тем, что для сравнения чисел с плавающей точкой используется оператор == или !=. Рассмотрим предупреждение V550.

И именно поэтому данная диагностика имеет низкую достоверность и располагается на 3-ем уровне. Большинство разработчиков, с которыми я общался, считают, что эта диагностика малополезна и отключают её, так как все срабатывания для их проекта являются ложными.

И часто сравнение с константой используется исключительно для того, чтобы проверить, задано ли некое значение по умолчанию, или оно изменилось. Действительно, в большинстве приложений типы float/double используются в очень простых алгоритмах. Поясню это псевдокодом. В этом случае точная проверка вполне уместна.

float value = 1.0f;
if (IsUserInputNewValue()) value = GetUserValue();
if (value == 1.0f) DefaultBehavior();
else Foo(value);

Здесь сравнение (value == 1.0f) корректно и безопасно.

Нет. Значит ли это, что V550 является неинтересной диагностикой? Процитирую фрагмент из статьи "О том, как мы опробовали статический анализ на своем проекте учебного симулятора рентгенэндоваскулярной хирургии", написанной одним из наших пользователей. Всё зависит от проекта.

Итак, на что здесь обращает наше внимание статический анализатор:

It's probably better to use a comparison with defined precision: fabs(A — B) > Epsilon. V550 An odd precise comparison: t != 0. objectextractpart.cpp 3401

D3DXVECTOR3 N = VectorMultiplication( VectorMultiplication(V-VP, VN), VN);
float t = Qsqrt(Scalar(N, N));
if (t!=0)
{ N/=t; V = V - N * DistPointToSurface(V, VP, N);
}

Подобные ошибки повторяются достаточно часто в данной библиотеке. Не скажу, что это стало для меня неожиданностью. Уже ранее наталкивался на некорректную работу с числами с плавающей точкой в этом проекте. Однако систематически проверять исходники на этот счет не было ресурсов. По результатам проверки стало ясно, что нужно дать разработчику почитать что-то для расширения кругозора в части работы с числами с плавающей точкой. Скинул ему ссылки на пару хороших статей. Посмотрим на результат. Сложно однозначно сказать, вызывает ли эта ошибка реальные сбои в работе программы. Текущее решение выставляет ряд требований к исходной полигональной сетке артерий, по которым моделируется растекание рентгеноконтрастного вещества. Если требования не выполнены, то возможны падения программы, или явно некорректная работа. Часть из этих требований получена аналитически, а часть — эмпирически. Не исключено, что эта вторая часть требований растет как раз из некорректной работы с числами с плавающей точкой. Нужно отметить, что не все найденные случаи употребления точного сравнения чисел с плавающей точкой являлись ошибкой.

Это делает невозможным создание списка «самого интересного». Как видите, то что неинтересно в одних проектах, представляет интерес в других.

Имеется возможность задавать с помощью настроек уровень предупреждений. Примечание. Данный вид настроек описан в документации (см. Например, если вы считаете, что диагностика V550 заслуживает пристального внимания, вы можете переместить её с третьего уровня на первый. «Как задать свой уровень для конкретной диагностики»).

Заключение

И не забывайте заглядывать в документацию, чтобы познакомиться с детальным описанием предупреждений. Теперь вы знаете, как начать изучение предупреждений анализатора, рассматривая самые интересные из них. Пример таких диагностик: V597, V1026. Иногда бывает, что за невзрачным, на первый взгляд, предупреждением кроется ад. Спасибо за внимание.

How to quickly check out interesting warnings given by the PVS-Studio analyzer for C and C++ code? Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Andrey Karpov.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть