Статичний аналіз - від знайомства до інтеграції

Втомившись від нескінченного code review або налагодження, часом замислюєшся, як спростити собі життя. І трохи пошукавши, ну чи випадково натрапивши, можна побачити чарівне словосполучення: "Статичний аналіз". Давайте подивимося, що це таке і як він може взаємодіяти з вашим проектом.

Статичний аналіз - від знайомства до інтеграції
Власне кажучи, якщо ви пишете якоюсь сучасною мовою, тоді навіть не здогадуючись про це ви пропускали його через статичний аналізатор. Справа в тому, що будь-який сучасний компілятор надає нехай і крихітний, але набір попереджень про потенційні проблеми в коді. Наприклад, компілюючи C++ код у Visual Studio ви можете побачити таке:

Статичний аналіз - від знайомства до інтеграції
У цьому висновку бачимо, що змінна було так і не була використана ніде у функції. Тож насправді ви майже завжди користувалися простим статичним аналізатором коду. Однак, на відміну від професійних аналізаторів, таких як Coverity, Klocwork або PVS-Studio, компілятором попередження можуть вказувати тільки на невеликий спектр проблем.

Якщо ви не знаєте, напевно, що таке статичний аналіз і як його впроваджувати, прочитайте цю статтющоб детальніше ознайомитися з цією методологією.

Навіщо потрібний статичний аналіз?

У двох словах: прискорення та спрощення.

Статичний аналіз дозволяє знайти безліч різних проблем у коді: починаючи від неправильного використання конструкцій мови, закінчуючи друкарськими помилками. Наприклад, замість

auto x = obj.x;
auto y = obj.y;
auto z = obj.z;

Ви написали такий код:

auto x = obj.x;
auto y = obj.y;
auto z = obj.x;

Як бачите, в останньому рядку з'явилася помилка. Наприклад, PVS-Studio видає таке попередження:

V537 Consider reviewing the correctness of 'y' item's usage.

Якщо хочете потикати в цю помилку руками, спробуйте готовий приклад на Compiler Explorer: *клік*.

І як ви розумієте, не завжди можна звернути увагу на подібні ділянки коду відразу і через це можна засісти за налагодження на добрий час, дивуючись, чому все працює так дивно.

Однак, це явна помилка. А якщо розробник написав неоптимальний код через те, що забув якусь тонкість мови? Або ж зовсім допустив у коді невизначена поведінка? На жаль, подібні випадки абсолютно звичайні і левова частина часу витрачається на те, щоб налагодити специфічно працюючий код, який містить помилки, типові помилки або undefined behavior.

Саме цих ситуацій і з'явився статичний аналіз. Це помічник для розробника, який вкаже йому на різні проблеми в коді і пояснить у документації, чому так писати не потрібно, до чого це може привести і як це виправити. Ось приклад, як це може виглядати: *клік*.

Більше цікавих помилок, які може виявити аналізатор, ви можете знайти у статтях:

Тепер, прочитавши цей матеріал та переконавшись у користі статичного аналізу, ви могли захотіти випробувати його у справі. Але з чого розпочати? Як інтегрувати новий інструмент у поточний проект? І як познайомити команду із ним? На ці запитання ви знайдете відповіді нижче.

Примітка. Статичний аналіз не замінює і скасовує таку корисну річ, як огляди коду. Він доповнює цей процес, допомагаючи заздалегідь помітити та виправити друкарські помилки, неточності, небезпечні конструкції. Набагато продуктивніше зосередитися при оглядах коду на алгоритмах і зрозумілості коду, а не над виглядом не там поставленої дужки або читати нудні функції порівняння.

0. Знайомство з інструментом

Все починається із пробної версії. Справді, складно зважитися впроваджувати щось у процес розробки, якщо ніколи до цього не бачив інструменту наживо. Тому насамперед варто завантажити пробну версію.

Що ви дізнаєтесь на цьому етапі:

  • Які є способи взаємодії з аналізатором;
  • Чи сумісний аналізатор з вашим середовищем розробки;
  • Які проблеми є зараз у ваших проектах?

Після того, як ви встановили собі все необхідне, то насамперед варто запустити аналіз всього проекту (Windows, Linux, MacOS). У випадку з PVS-Studio у Visual Studio ви побачите подібну картину (клікабельно):

Статичний аналіз - від знайомства до інтеграції
Справа в тому, що зазвичай на проекти з великою кодовою базою статичні аналізатори видають величезну кількість попереджень. Немає необхідності виправляти їх усі, тому що ваш проект вже працює, а отже ці проблеми не є критичними. Однак ви можете подивитися на найцікавіші попередження та виправити їх за потреби. Для цього потрібно відфільтрувати висновок та залишити лише найбільш достовірні повідомлення. У плагіні PVS-Studio для Visual Studio це робиться фільтрацією за рівнями та категоріями помилок. Для найбільш точного висновку залиште увімкненими тільки Високий и Загальне (теж клікабельно):

Статичний аналіз - від знайомства до інтеграції
Справді, 178 попереджень переглянути значно простіше, ніж кілька тисяч.

У вкладках Medium и низький часто трапляються хороші попередження, проте в ці категорії занесені діагностики, які мають меншу точність (достовірність). Докладніше про рівні попереджень та варіанти роботи під Windows можна подивитися тут: *клік*.

Успішно переглянувши найцікавіші помилки (і успішно виправивши їх) варто придушити попередження, що залишилися. Це потрібно для того, щоб нові попередження не губилися серед старих. До того ж, статичний аналізатор – це помічник для програміста, а не список для багів. 🙂

1. Автоматизація

Після знайомства настає час налаштування плагінів та інтеграції до CI. Це потрібно зробити до того, як програмісти почнуть використовувати статичний аналізатор. Справа в тому, що програміст може забути включити аналіз або зовсім не захотіти. Для цього потрібно зробити деяку фінальну перевірку всього, щоб неперевірений код не міг потрапити до загальної галузі розробки.

Що ви дізнаєтесь на цьому етапі:

  • Які варіанти автоматизації надає інструмент;
  • Чи сумісний аналізатор з вашою складальною системою.

Так як ідеальної документації не існує, іноді доводиться писати в підтримку. Це нормально і ми раді вам допомогти. 🙂

А тепер приступимо до сервісів безперервної інтеграції (CI). Будь-який аналізатор можна впровадити у них без будь-яких серйозних проблем. Для цього потрібно створити окремий етап у pipeline, який зазвичай знаходиться після складання та юніт-тестів. Робиться це за допомогою різних консольних утиліт. Наприклад, PVS-Studio надає такі утиліти:

Для інтеграції аналізу в CI потрібно зробити три речі:

  • Встановити аналізатор;
  • Запустити аналіз;
  • Доставити результати.

Наприклад, для встановлення PVS-Studio на Linux (Debian-base) потрібно виконати такі команди:

wget -q -O - https://files.viva64.com/etc/pubkey.txt 
    | sudo apt-key add -
sudo wget -O /etc/apt/sources.list.d/viva64.list 
  https://files.viva64.com/etc/viva64.list
  
sudo apt-get update -qq
sudo apt-get install -qq pvs-studio

У системах під керуванням Windows відсутня можливість встановити аналізатор із пакетного менеджера, проте є можливість розгорнути аналізатор із командного рядка:

PVS-Studio_setup.exe /verysilent /suppressmsgboxes 
/norestart /nocloseapplications

Докладніше про розгортання PVS-Studio у системах під керуванням Windows можна почитати *тут*.

Після встановлення слід запустити безпосередньо аналіз. Однак робити це рекомендується лише після того, як пройшла компіляція та тести. Це з тим, що з статичного аналізу зазвичай потрібно вдвічі більше часу, ніж компіляції.

Оскільки спосіб запуску залежить від платформи та особливостей проекту, я покажу варіант для C++ (Linux) як приклад:

pvs-studio-analyzer analyze -j8 
                            -o PVS-Studio.log
plog-converter -t errorfile PVS-Studio.log --cerr -w

Перша команда виконає аналіз, а друга конвертіе звіт у текстовий формат, виведе його на екран і поверне відмінний від 0 код повернення у разі наявності попереджень. Такий механізм зручно використовуватиме блокування складання за наявності повідомлень про помилки. Однак, ви завжди можете прибрати прапор -w і не блокувати складання, що містить попередження.

Примітка. Текстовий формат – це незручно. Він наводиться просто для прикладу. Зверніть увагу на цікавіший формат звіту — FullHtml. Він дозволяє здійснювати навігацію за кодом.

Докладніше про налаштування аналізу на CI можна прочитати у статті "PVS-Studio та Continuous Integration" (Windows) або "Як налаштувати PVS-Studio в Travis CI(Linux).

Добре, ви налаштували роботу аналізатора на складальному сервері. Тепер, якщо хтось залив неперевірений код, падатиме етап перевірки, і ви зможете виявити проблему, проте це не зовсім зручно, оскільки ефективніше перевіряти проект не після того, як відбулося злиття гілок, а до нього, на етапі pull request' а.

В цілому налаштування аналізу pull request'а не сильно відрізняється від звичайного запуску аналізу на CI. За винятком необхідності отримати список змінених файлів. Зазвичай їх можна отримати, запросивши різницю між гілками за допомогою git:

git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list

Тепер необхідно передати аналізатору на вхід цей перелік файлів. Наприклад, у PVS-Studio це реалізовано за допомогою прапора -S:

pvs-studio-analyzer analyze -j8 
                            -o PVS-Studio.log 
                            -S .pvs-pr.list

Докладніше про аналіз pull request'ів можна дізнатися *тут*. Навіть якщо вашого CI немає у списку вказаних у статті сервісів, вам буде корисний загальний розділ, присвячений теорії цього аналізу.

Налаштувавши аналіз pull request'ів ви зможете блокувати комміти, що містять попередження, тим самим створивши кордон, який неперевірений код не зможе перетнути.

Це все безперечно добре, проте хотілося б мати можливість подивитися всі попередження в одному місці. Не лише від статичного аналізатора, а й від юніт-тестів або від динамічного аналізатора. Для цього існують різні послуги та плагіни. PVS-Studio, наприклад, має плагін для інтеграції в SonarQube.

2. Інтеграція на машини розробників

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

Як найпростіший варіант – розробники можуть встановити необхідний аналізатор. Однак це займе багато часу та відверне їх від розробки, тому ви можете автоматизувати цей процес, використовуючи установник та потрібні прапори. Для PVS-Studio є різні прапори для автоматизованої установки. Втім, завжди є пакетні менеджери, наприклад Chocolatey (Windows), Homebrew (macOS) або десятки варіантів для Linux.

Потім потрібно буде встановити необхідні плагіни, наприклад, для Visual Studio, IDEA, Rider і т.п.

3. Щоденне використання

На цьому етапі час сказати кілька слів про способи прискорення роботи аналізатора при щоденному використанні. Повний аналіз всього проекту займає дуже багато часу, проте часто ми змінюємо код разом у всьому проекті? Навряд чи існує настільки масштабний рефакторинг, що відразу торкнеться всієї кодової бази. Кількість файлів, що змінюються, за раз рідко перевищує десяток, тому їх і є сенс аналізувати. Для такої ситуації існує режим інкрементального аналізу. Тільки не лякайтеся, це ще один інструмент. Це спеціальний режим, який дозволяє аналізувати лише змінені файли та їх залежності, причому це відбувається автоматично після збирання, якщо ви працюєте в IDE з встановленим плагіном.

Якщо аналізатор виявить у нещодавно зміненому коді проблеми, то повідомить про це самостійно. Наприклад, PVS-Studio скаже вам про це за допомогою оповіщення:

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

Подібні статті дають всю необхідну інформацію для повсякденного використання і не забирають багато часу. 🙂

Ще на етапі знайомства з інструментом ми придушили багато попереджень під час одного з перших запусків. На жаль, але статичні аналізатори не ідеальні, тому іноді видають хибні спрацьовування. Придушити їх зазвичай легко, наприклад, у плагіні PVS-Studio для Visual Studio достатньо натиснути на одну кнопку:

Статичний аналіз - від знайомства до інтеграції
Однак, ви можете не тільки придушувати їх. Наприклад, ви можете повідомити про наявність проблеми. Якщо помилкове спрацювання можна виправити, то в майбутніх оновленнях ви можете звернути увагу на те, що з кожним разом стає все менше і менше специфічних для вашої кодової бази помилкових спрацьовувань.

Після інтеграції

Ось ми і пройшли всі етапи інтеграції статичного аналізу в процес розробки. Незважаючи на важливість налаштування подібних інструментів на CI, найголовнішим місцем запуску є комп'ютер розробника. Адже статичний аналізатор – це не суддя, який каже десь далеко від вас, що код нікуди годиться. Навпаки, це помічник, який підказує, якщо ви втомилися і нагадує, якщо ви про щось забули.

Щоправда, без регулярного використання статичний аналіз навряд чи значно спростить розробку. Адже найголовніша його користь для розробника полягає не так у пошуку складних і спірних ділянок коду, як у ранньому їх виявленні. Погодьтеся, що виявити проблему, коли редагування пішли на тестування, не тільки неприємно, а й дуже довго. Статичний аналіз при регулярному використанні переглядає кожну зміну прямо на вашому комп'ютері і повідомляє про підозрілі місця під час роботи над кодом.

А якщо ви чи ваші колеги все ще не впевнені, чи варто впроваджувати аналізатор, то пропоную зараз перейти до читання статті.Причини впровадження в процес розробки статичного аналізатора коду PVS-StudioУ ній розібрано типові побоювання розробників про те, що статичний аналіз забиратиме їхній час і так далі.

Статичний аналіз - від знайомства до інтеграції

Якщо хочете поділитися цією статтею з англомовною аудиторією, прошу використати посилання на переклад: Maxim Zvyagintsev. Static Analysis: From Getting Started to Integration.

Джерело: habr.com

Додати коментар або відгук