Ik zag een publicatie die PVS onder Linux had leren analyseren, en besloot deze op mijn eigen projecten uit te proberen. En dit is wat er uit voortkwam.
Ik heb een proefsleutel aangevraagd en deze werd dezelfde dag nog naar mij verzonden.
Redelijk duidelijke documentatie
We zijn erin geslaagd de analyser zonder problemen te starten. Er is ook hulp voor consoleopdrachten beschikbaar (hoewel er hier enkele klachten zijn, zie sectie Tegens).
Mogelijkheid tot multi-threaded analyse
De analyser heeft een "standaard" optie -j, waardoor analyses parallel in verschillende taken kunnen worden uitgevoerd. Dit bespaart veel tijd.
Alle documentatie staat op hun website, ik kan alleen maar zeggen dat als je project is gebouwd met CMake, alles heel eenvoudig is.
Goede diagnostische beschrijvingen
Als u uitvoer genereert in de modus fullhtml, dan heeft elk bericht een link naar een diagnostische beschrijving, met uitleg, codevoorbeelden en extra links.
Helaas maakt PVS soms syntaxisfouten en genereert het valse positieve berichten wanneer de code volledig correct is.
Er is bijvoorbeeld een functie die retourneert 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));
}
Ja, trefwoord auto Kan betekenen void, daar is het voor auto. Maar PVS produceerde de volgende berichten:
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.
Zeer trage website
Ja, in de webinterface staat naast elk bericht een link naar de bijbehorende diagnosebeschrijving met voorbeelden. Maar als je op een link klikt, moet je behoorlijk lang wachten, en soms gebeurt dat ook 504 Gateway Time-out.
taal
Alle beschrijvingen zijn in het Russisch, wat geweldig is. Maar links uit het rapport leiden altijd naar de Engelse versie. Het zou leuk zijn om de taal te kunnen veranderen, zodat u de diagnostiek onmiddellijk in het Russisch kunt bekijken. Ik heb zo'n optie niet gevonden in de interface.
Het is lastig om via de console met diagnostische niveaus te werken
Laten we beginnen met het feit dat de twee gebruikte commando's (this pvs-studio-analyzer и plog-converter) verschillende formaten voor het specificeren van diagnostiek.
Help voor pvs-studio-analyzer leest:
-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
Ik heb er lang over gedaan om uit te vinden waar ik heen moest toevoegen (“de waarden toevoegen”) toetsen. Ik heb geprobeerd ze op te sommen, gescheiden door komma's:
pvs-studio-analyzer analyze ... -a 1,4,16
Ik heb verschillende keren geprobeerd de sleutel te registreren:
pvs-studio-analyzer analyze ... -a 1 -a 4 -a 16
En pas toen besefte ik dat dit bitmaskers waren! En dat heb je nodig opsommenEn niet toevoegen betekenissen. Om bijvoorbeeld algemene diagnostiek, diagnostiek voor micro-optimalisaties en MISRA te krijgen, moet u ze samenvatten (4 + 8 + 32 = 44):
pvs-studio-analyzer analyze ... -a 44
Het gebruik van bitmaskers in gebruikersinterfaces is over het algemeen een slechte vorm. Dit alles zou intern kunnen worden samengevat en er zou een reeks vlaggen voor de gebruiker kunnen worden ingesteld.
Daarnaast is er ook een nutsvoorziening plog-converter, dat voor mensen leesbare statische analyse-informatie genereert. Ze heeft andere problemen.
Hulp voor het programma plog-converter meldt:
-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
Hier verschenen enkele “niveaus” die er voorheen niet waren, en ik heb er ook niets over gevonden in de documentatie.
Over het algemeen is het niet duidelijk. Daarom heb ik alles op het maximale gezet.
Een stel stomme vloeken op Catch
Twee van de drie projecten die ik heb geanalyseerd, gebruiken een unit-testbibliotheek Catch2. En het leeuwendeel van de berichten (!!! 90 van de 138 in de ene en 297 van de 344 in de andere!!!) heeft de volgende vorm:
Er wordt geen rekening gehouden met multithreading
Er zijn veel valse positieven over zogenaamd onveranderlijke variabelen of eindeloze lussen, terwijl het werken met deze variabelen vanuit verschillende threads plaatsvindt, en als dit niet zo zou zijn, zouden unit-tests niet werken.
Kan een statische analysator hier echter überhaupt rekening mee houden? Weet het niet.
PVS heeft geen echte bugs gevonden in mijn open source projecten Uitbarsting и Proxima, evenals in een werkontwerp, dat ik om voor de hand liggende redenen niet kan presenteren. Het is waar dat het de moeite waard is om in gedachten te houden dat sommige tekortkomingen al eerder zijn opgemerkt en gecorrigeerd Cppcontrole и scan-build.
Over het algemeen is de indruk van al deze analysatoren ongeveer hetzelfde: ja, ze vangen iets op, soms zelfs iets belangrijks, maar over het algemeen is de compiler voldoende.
Het is mogelijk (en dat denk ik persoonlijk graag) dat ons team softwareontwikkelingspraktijken gebruikt die ons in staat stellen een minimale hoeveelheid waardeloze code te genereren. Het is beter geen problemen te creëren dan ze heldhaftig te overwinnen.
Daarom neem ik de vrijheid om wat advies te geven over hoe je in C++ moet schrijven op een manier dat niemand de benen eraf schiet of iemand met een hark op zijn voorhoofd slaat.
Maak optimaal gebruik van compilerdiagnostiek
Ons team gebruikt (en adviseert u dit te doen) de volgende compilatiemogelijkheden:
Schakel ze in in uw project en leer veel over uw code.
Houd je aan de standaard
Probeer geen platformafhankelijke dingen te gebruiken als er standaardanalogen zijn, en als je absoluut niet zonder hen kunt, verpak ze dan in speciale blokken voor macro's (of iets anders) en laat je code eenvoudigweg niet compileren onder niet-ondersteunde omstandigheden.
Houd u aan de standaard werkingssemantiek
Optellen moet optellen zijn, vermenigvuldigen moet vermenigvuldigen zijn, functieaanroep moet functieaanroep zijn, kopiëren moet kopiëren zijn, carry moet carry zijn, container moet itereerbaar zijn, iterator moet promotie hebben ++ en dereferentie *. Enzovoort.
Ik denk dat het idee duidelijk is. Er zijn gevestigde conventies die niet bindend zijn, maar die alle gebruikers en lezers van uw code verwachten te zien. Probeer niet anderen te slim af te zijn, anders ben je jezelf te slim af.
Schrijf compatibele code
Allereerst bedoel ik de standaardbibliotheek. Het is zeer wenselijk dat de interfaces van uw klassen en functies kunnen worden gebruikt met standaard- en andere bibliotheken (bijvoorbeeld Boost).
Kijk gerust eens naar de STL- en Boost-interfaces. Op zeldzame uitzonderingen na zul je daar een waardig rolmodel zien.
Haal het maximale uit open source-tools
Voor dezelfde statische analyse zijn er ten minste twee open gratis tools die slechts één keer aan elk project met het CMake-buildsysteem kunnen worden gekoppeld.
Ten slotte zou ik willen benadrukken dat ik er niet voor pleit om geen PVS of andere statische analysatoren te gebruiken. Maar ik moedig je aan om na te denken over hoe het gebeurde dat de statische analysator voortdurend significante fouten in je code vindt.
Dit is slechts een gevolg. We moeten de oorzaak zoeken en elimineren.