Незалежны агляд PVS-Studio (Linux, C++)

Убачыў публікацыю аб тым, што PVS такі навучыўся аналізаваць пад Лінуксамі, і вырашыў паспрабаваць на сваіх праектах. І вось што з гэтага атрымалася.


Змест

  1. Плюсы
  2. Мінусы
  3. Вынікі
  4. пасляслоўе

Плюсы

Спагадлівая падтрымка

Я запытаў пробны ключ, у той жа дзень мне яго даслалі.

Досыць зразумелая дакументацыя

Запусціць аналізатар удалося без асаблівых праблем. Даведка да кансольных каманд таксама маецца (хоць тут ёсць нараканні, гл. падзел Мінусы).

Магчымасць шматструменнага аналізу

У аналізатара ёсць "стандартная" опцыя -j, якая дазваляе праводзіць аналіз паралельна ў некалькіх задачах. Гэта моцна эканоміць час.

Добрая візуалізацыя

Шмат розных фарматаў вываду, ад тэкставага да невялікай вэб-морды. Вэб-морда зручная, лаканічная, з падказкамі побач з радкамі ў кодзе і спасылкамі на апісанні дыягностык.

Простая інтэграцыя ў зборку

Уся дакументацыя ёсць на іх сайце, скажу толькі, што калі ваш праект збіраецца з дапамогай CMake, тое ўсё вельмі проста.

Добрыя апісанні дыягностык

Калі генераваць выснову ў рэжыме fullhtml, то ў кожнага паведамлення ёсць спасылка на апісанне дыягностыкі, з тлумачэннямі, прыкладамі кода і дадатковымі спасылкамі.

Мінусы

Няведанне аналізатарам мовы C++

Нажаль, PVS часам памыляецца ў сінтаксісе і генеруе прытворнададатныя паведамленні пры цалкам карэктным кодзе.

Напрыклад, ёсць функцыя, якая вяртае void:

template <typename T>
auto copy (const void * source, void * destination)
    ->
        std::enable_if_t
        <
            std::is_copy_constructible<T>::value
        >
{
    new (destination) T(*static_cast<const T *>(source));
}

Так, ключавое слова auto можа азначаць void, на тое яно і аўтаматычны. Але PVS выдаў вось такія паведамленні:

dynamic_tuple_management.hpp:29:1: error: V591 Non-void function should return a value.
dynamic_tuple_management.hpp:29:1: error: V2542 Function with a non-void return type should return a value from all exit paths.

Вельмі тармазнуты сайт

Так, у вэб-мордзе побач з кожным паведамленнем ёсць спасылка на адпаведнае апісанне дыягностыкі з прыкладамі. Але пры націску на спасылку чакаць даводзіцца дастаткова доўга, а часам бывае і 504 Тайм-аўт шлюза.

Мова

Усе апісанні ёсць на рускай, гэта выдатна. Але спасылкі са справаздачы заўсёды вядуць на ангельскую версію. Было б нядрэнна мець магчымасць пераключаць мову, каб праглядаць дыягностыкі можна было адразу на рускай. У інтэрфейсе такой магчымасці я не знайшоў.

Няёмка працаваць з узроўнямі дыягностык праз кансоль

Пачнём з таго, што ў двух выкарыстоўваных каманд (гэта pvs-studio-analyzer и plog-converter) розныя фарматы задання дыягностык.

Даведка да pvs-studio-analyzer абвяшчае:

-a [MODE], --analysis-mode [MODE]
    MODE defines the type of warnings:
    1 - 64-bit errors;
    2 - reserved;
    4 - General Analysis;
    8 - Micro-optimizations;
    16 - Customers Specific Requests;
    32 - MISRA.
    Modes can be combined by adding the values
    Default: 4

Доўга спрабаваў зразумець, куды ж трэба дадаваць ("adding the values") ключы. Спрабаваў пералічваць праз коску:

pvs-studio-analyzer analyze ... -a 1,4,16

Спрабаваў прапісваць ключ некалькі разоў:

pvs-studio-analyzer analyze ... -a 1 -a 4 -a 16

І толькі потым я здагадаўся, што гэта ж бітавыя маскі! І трэба сумаваць, А не дадаваць значэння. Напрыклад, каб атрымаць агульныя дыягностыкі, дыягностыкі па мікрааптымізацыях і MISRA, трэба іх падсумаваць (4 + 8 + 32 = 44):

pvs-studio-analyzer analyze ... -a 44

Выкарыстанне бітавых масак у карыстацкіх інтэрфейсах гэта, як правіла, благі тон. Усё гэта прасумаваць можна было і ўсярэдзіне, а карыстачу выставіць набор сцягоў.

Акрамя таго, ёсць яшчэ ўтыліта plog-converter, якая генеруе чалавекачытаемую інфармацыю аб статычным аналізе. У яе іншыя замарочкі.

Даведка да праграмы plog-converter паведамляе:

-a, --analyzer            Specifies analyzer(s) and level(s) to be
                          used for filtering, i.e.
                          'GA:1,2;64:1;OP:1,2,3;CS:1;MISRA:1,2'
                          Default: GA:1,2

Тут з'явіліся нейкія "ўзроўні", якіх раней нідзе не было, і ў дакументацыі я пра іх таксама нічога не знайшоў.

Увогуле, незразумела. Таму я ўсё выстаўляў па максімуме.

Куча бязглуздай лаянкі на Catch

У двух з трох праектаў, якія я аналізаваў, выкарыстоўваецца бібліятэка модульнага тэсціравання Catch2. І ільвіная доля паведамленняў (!!! 90 з 138 у адным і 297 з 344 у іншым !!!) маюць наступны выгляд:

Незалежны агляд PVS-Studio (Linux, C++)

Не ўлічвае шматструменнасць

Шмат прытворнададатных спрацоўванняў аб нібы нязменных зменных ці бясконцых цыклах, пры гэтым праца з дадзенымі зменнымі адбываецца з розных струменяў, і калі б гэта было не так, то модульныя тэсты б не спрацоўвалі.

Незалежны агляд PVS-Studio (Linux, C++)

Зрэшты, ці можа ўвогуле такое ўлічыць статычны аналізатар? Не ведаю.

Вынікі

PVS не знайшоў ніводнай сапраўднай памылкі ў маіх адкрытых праектах Выбух и Праксіма, а таксама ў працоўным праекце, які я, па зразумелых прычынах, прад'явіць не магу. Праўда, варта мець на ўвазе, што сякія-такія недапрацоўкі ўжо былі адлоўленыя і выпраўленыя раней з дапамогай Cppcheck и scan-build.

У цэлым уражанне ад усіх гэтых аналізатараў прыкладна аднолькавае: так, нешта яны ловяць, часам нават нешта важнае, але ў цэлым кампілятара хапае.

Магчыма (і асабіста мне прыемна так думаць), што наша каманда выкарыстоўвае такія практыкі распрацоўкі ПЗ, якія дазваляюць генераваць мінімальную колькасць гаўнакода. Лепш не ствараць праблемы, чым гераічна пераадольваць іх.

Таму бяру на сябе смеласць даць некалькі парад аб тым, як пісаць на мове C++ так, каб не адстрэльваць нікому ногі і не абграбаць граблямі па лбе.

Выкарыстоўвайце дыягностыкі кампілятара па максімуме

Наша каманда выкарыстоўвае (і вам раіць) наступныя опцыі кампіляцыі:

-Werror

-Wall
-Wextra
-Wpedantic

-Wcast-align
-Wcast-qual
-Wconversion
-Wctor-dtor-privacy
-Wenum-compare
-Wfloat-equal
-Wnon-virtual-dtor
-Wold-style-cast
-Woverloaded-virtual
-Wredundant-decls
-Wsign-conversion
-Wsign-promo

Уключыце іх у сваім праекце, даведаецеся шмат новага аб сваім кодзе.

Прытрымлівайцеся стандарту

Старайцеся не выкарыстоўваць платформазалежныя рэчы, калі ёсць стандартныя аналагі, а калі ўжо без іх зусім не абысціся, заварочвайце іх у спецыяльныя блокі пад макросню (ці неяк яшчэ) і проста не давайце скампіляваць ваш код у непадтрымліваемых умовах.

Прытрымвайцеся стандартнай семантыкі аперацый

Складанне павінна быць складаннем, множанне - множаннем, выклік функцыі - выклікам функцыі, капіраванне павінна капіяваць, перанос - пераносіць, кантэйнер павінен быць итерируем, итератор павінен мець прасоўванне ++ і разнайменне *. І гэтак далей, і гэтак далей.

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

Пішыце сумяшчальны код

У першую чаргу я маю на ўвазе стандартную бібліятэку. Вельмі пажадана, каб інтэрфейсы вашых класаў і функцый маглі быць скарыстаны са стандартнымі і іншымі бібліятэкамі (напрыклад, Бустам).

Не саромейцеся падглядаць у інтэрфейсы STL і Boost. За рэдкімі выключэннямі тамака вы ўбачыце годны прыклад для пераймання.

Выкарыстоўвайце па максімуме адкрытыя прылады

Для таго ж статычнага аналізу існуюць як мінімум два адкрытыя бясплатныя прылады, якія на рахунак «раз» падлучаюцца да любога праекту з сістэмай зборкі CMake.

Падрабязней пра гэта можна пачытаць у маёй нядаўняй публікацыі.

пасляслоўе

Напрыканцы падкрэслю, што я не заклікаю не выкарыстоўваць PVS ці якія-небудзь іншыя статычныя аналізатары. Але я заклікаю задумацца аб тым, як так атрымалася, што статычны аналізатар увесь час знаходзіць у вашым кодзе істотныя памылкі.

Гэтае толькі следства. Трэба шукаць і ўстараняць прычыну.

Крыніца: habr.com

Дадаць каментар