Как быстро внедрить статический анализ в большой проект?




Итак, вы – разработчик в проекте, в котором много (или даже очень много) исходного кода. Например, более 100 мегабайт.

Picture 1

Вы начитались статей про проверку open source проектов и захотели проверить свой собственный проект каким-нибудь анализатором кода. Вы проверили проект и получили более тысячи сообщений от анализатора. Тысяча – это оптимистичный вариант. Может быть и более десятка тысяч. Но вы же не ленивый разработчик? Вы начали просматривать их. И, о ужас, уже пятое сообщение анализатора оказалось реальной ошибкой! А также седьмое, девятое, двенадцатое и пятнадцатое. Вы выписали себе еще десяток реальных ошибок, на которые указал анализатор и направляетесь к боссу со словами:

"Шеф, смотри. Я скачал крутой анализатор. Он нам уже только за полчаса нашел десять реальных ошибок. А всего он выдал тысячу (две, три, четыре) сообщений. Давай купим этот анализатор, мы с ребятами займемся и все сообщения поправим за две-три недели. И потом, когда все поправим, он нам будет выдавать 0 сообщений. А значит мы – крутые программисты и делаем качественный код!"

И хотя вы уже мысленно подставляете грудь для новой медали (ведь вы радеете за качество проекта!), шеф ваш очень вероятно ответит примерно так:

"Тебе что, заняться нечем? Ты всю команду хочешь на три недели отвлечь для правки ошибок, а у нас релиз через месяц! Ну и что, что ошибки реальные? Жили как-то с ними и ничего. Да, я понимаю, что было бы здорово не делать ошибки в новом коде. Ну так вы и не делайте! А старый код трогать не позволю! Он уже оттестирован и клиенты за него заплатили. А кто за три недели работы команды платить будет? Так что не будем мы покупать анализатор, да и код старый трогать не будем. А у тебя видимо текущие задачи кончились. Так мы сейчас тебе подкинем. И чтобы завтра готово было!"

Реальный сценарий? Реальный. Хуже всего то, что хорошая идея внедрения статического анализа заглохла от того, чтоб надо проработать все сообщения, которые выдает анализатор кода. Ведь если каждый прогон анализатора будет выдавать тысячу сообщений, то понять, где новые сообщения, а где старые будет невозможно. Или все-таки есть способ решить эту проблему?

Как этот вопрос решает в PVS-Studio?

Пару релизов назад в PVS-Studio появился механизм для подавления старых или "неинтересных" сообщений от анализатора кода. К версии 5.22 мы его окончательно отладили, отработали и теперь он оказался настолько удобным, что мы его рекомендуем использовать всем, кто задумывается о внедрении статического анализа в своем проекте. А я сейчас расскажу, как этим пользоваться.

Итак, перед вами проект на 5 миллионов строк кода (всего лишь для примера), в котором 150 мегабайт исходников. Вы проверили его анализатором и получили несколько тысяч сообщений общего назначения (General Analysis). Вы и рады бы их исправить, да времени менеджер проекта не выделяет.

OK, не вопрос. После завершения анализа всего солюшена идем в меню PVS-Studio -> Suppress Messages... Диалог простой, нажимаем "Suppress Current Messages", затем Close. В итоге у вас окне PVS-Studio останется 0 сообщений. И даже если вы запустите еще раз анализ всего кода – после завершения анализа будет 0 сообщений. Зато вот если вы начнете писать новый код или модифицировать старый, то на этот код анализатор уже будет ругаться. Если конечно вы не напишете его сразу идеальным.

Как это работает?

Работает данный механизм довольно просто. Вернее, сейчас это просто, но сколько экспериментов было поставлено, чтобы прийти к такому варианту... Ну да ладно, что же происходит с точки зрения пользователя, когда он нажимает кнопку "Suppress Current Messages"?

В папке проекта создается база из .suppress-файлов. На каждый проект (.vcxproj-файл) создается рядом свой .suppress-файл. В нем хранится информация обо всех сообщения, которые выданы были анализатором при проверке этого проекта. С этими сообщениями мы и сравниваем результаты каждого нового анализа.

Сообщения естественно сравниваются не в лоб. Мы учитываем код сообщения, текст текущей строки кода, а также текст предыдущей и следующей строк кода. А вот номер строки мы наоборот не учитываем: ведь если сообщение выдавалось на конец файла (и так оно хранится в базе), то вставка строк в начало файла хоть и приведет к изменению строки выдачи сообщения. Мы это отследим и не будем лишний раз выдавать "неинтересное" сообщение. А вот если изменилась одна из строк (предыдущая, текущая или следующая), то мы уже ругаемся, т.к. контекст сообщения был задет, и можно считать это сообщение уже выданным на новый (модифицированный) код.

Что делать с этими. suppress файлами? Если PVS-Studio запускается на одной машине, скажем билд-сервере, то можно хранить эти файлы прямо в папках проектов. Если это не удобно (например, делается чистая сборка), то перед запуском анализатора можно копировать файлы в папку проекта с помощью robocopy из другого места – он сохраняет структуру папок.

Если с анализатором работают несколько разработчиков, то .suppress-файлы можно заложить в репозиторий. Возникает вопрос – а как синхронизировать эти .suppress файлы между разработчиками? С одной стороны ответ прост – это XML, так что нет проблем. Но с другой стороны оказывается, что синхронизировать эти файлы (да и вообще как-то их модифицировать) и не надо. Достаточно один раз при внедрении анализатора их создать, а больше их модифицировать не зачем. Ну и стараться при этом поддерживать 0 сообщений от анализатора на проекте в дальнейшем.

Примечание. А как же поддерживать 0 сообщений от анализатора в дальнейшем, если он нет, нет, да и выдаёт ложные предупреждения? На этот случай есть несколько способов для подавления отдельных предупреждений. Про этот будет сказано ниже.

Ну и для чего этот механизм?

Если вдруг кто-то еще не понял, то приведу абсолютно конкретный пример. Можно добавить все сообщения в такую базу (получим 0 сообщений при проверке). Дальше на билд-сервере каждую ночь запускается анализатор (как настроить запуск анализатора на билд-сервере), который выдает только новые сообщения, то есть сообщения на новый код, написанный командой за день. Эти сообщения сохраняются не только в .plog (отчет анализатора в xml-формате), но в текстовый файл рядом. А этот текстовый файл уже можно рассылать по почте участникам проекта с помощью любой подходящей программы. Например, с помощью SendEmail.

Утром люди видят сообщения от анализатора в своей почте и могут править ошибки даже без установки PVS-Studio на свои машины. Ну а если все-таки хочется отрыть отчет (.plog), то он доступен на билд-сервере. С помощью этого трюка можно здорово сэкономить на лицензиях на PVS-Studio.

Кстати вы можете настроить какие сообщения (точнее каких уровней) должны попадать в текстовый отчет. Это делается с помощью опции OutputLogFilter, которая находится на вкладке Specific Analyzer Settings настроек PVS-Studio. Мы рекомендуем включать в текстовый файл сообщения General Analysis Level1 и Level 2.

Небольшая оговорка про инкрементальный анализ

Мы все-таки рекомендуем прежде всего разработчикам использовать PVS-Studio в том числе и на локальных машинах в режиме инкрементального анализа. Речь идет о галочке "Analysis after Build (Modified files only)" в меню PVS-Studio. При включенной галочке анализатор следит за вашей работой и автоматически запускается для тех файлов, которые были скомпилированы (отслеживает модификацию .obj-файлов). Если анализатор ничего не найдет – то вы даже не заметите, что он запускался. А если найдет, то будет всплывающее сообщение об ошибках.

Инкрементальный анализ поддерживает базу "неинтересных" сообщений. Если у вас такая база есть, то сообщения от инкрементального анализа будут только про новый код. А если нет, то полностью на файл, который анализируется.

Режим инкрементального анализа позволяет исправлять ошибки сразу же при их появлении, еще до того, как ошибка окажется в системе контроля версий. А как известно из Макконнелла, исправление ошибок на этом этапе самое дешевое. Поэтому при наличии возможности мы рекомендуем использовать PVS-Studio и при ежедневных проверках на сервере, и в режиме инкрементального анализа на машинах программистов.

Как поправить сообщения, находящиеся в базе?

Хорошо, вы внедрили статический анализ на проекте, анализатор выдает вам не более нескольких сообщений в день, которые вы с командой сразу же правите. Отлично. Но тут выдалась неделька свободного времени, которое можно потратить на правку старых ошибок. Как до них добраться? Есть два варианта.

  • Вы можете через команду "Suppress Messages..." вызвать диалоговое окно, в котором появится галочка "Display Suppressed Messages". Включите ее и появятся сообщения.
  • Либо, если у вас настроен ежедневный запуск на билд-сервере, то вы просто идете в папку с результатами последнего анализа и видите там следующие файлы:
    • SolutionName.plog – лог с только новыми сообщениями;
    • SolutionName.plog.txt – текстовый лог, тоже самое что и SolutionName.plog;
    • SolutionName_WithSuppressedMessages.plog – все сообщения, включая "неинтересные".

Вот с этим файлом SolutionName_WithSuppressedMessages.plog и надо работать. Открываете его и получаете все сообщения. В первое время этот файл будет большой, так как сообщений много. Но если вы их хотя бы иногда будете править, то со временем он станет маленький, а может и вовсе вы от него сможете отказаться (и от .suppress-файлов соответственно тоже).

Важно понять вот что. Если у вас появляется время и возможность, вы всегда можете вернуться к старым "неинтересным" сообщениям и поправить их. Мы рекомендуем это делать, так как все-таки ошибки есть ошибки и их надо править.

А это не противоречит функции Mark as False Alarm?

В PVS-Studio есть команда Mark As False Alarm – разметить как ложное срабатывание. Это когда в строку с сообщением добавляется комментарий вида //-V501. Встретив такой комментарий анализатор не будет выдавать сообщение V501 на эту строку.

Механизм, описываемый в этой статье и Mark As False Alarm никак не противоречат друг другу. Но они служат для немного разных целей. Массовое подавление неинтересных сообщений – для массовой разметки при внедрении анализатора в проект. А Mark As False Alarm – для того, чтобы анализатор не ругался на отдельные фрагменты.

В принципе можно было бы и раньше разметить весь код как False Alarm, но обычно людям страшновато делать столько много правок в коде. Кроме того, не понятно, как работать со старыми ошибками – убирать все, что размечено как False Alarm? А если там действительно false alarm.

Но и использовать механизм массового подавления для подавления отдельных сообщений тоже неправильно.

В общем это два механизма, решающих разные задачи. Не надо их путать.

Заключение

Итак, подход к внедрению статического анализа в живом проекте выглядит так:

  • Размечаем все сообщения как "неинтересные" с помощью команды "Suppress Messages...".
  • Теперь при следующем запуске анализатор будет выдавать сообщения только на новый код.
  • При необходимости всегда можно исправить ошибки, которые были скрыты при внедрении.

Это позволяет начать получать пользу от статического анализа сразу же.

Дополнительные ссылки



Найдите ошибки в своем C, C++, C# и Java коде

Предлагаем попробовать проверить код вашего проекта с помощью анализатора кода PVS-Studio. Одна найденная в нём ошибка скажет вам о пользе методологии статического анализа кода больше, чем десяток статей.

goto PVS-Studio;


Найденные ошибки

Проверено проектов
346
Собрано ошибок
13 188

А ты совершаешь ошибки в коде?

Проверь с помощью
PVS-Studio

Статический анализ
кода для C, C++, C#
и Java

goto PVS-Studio;