Jeg så en publikation, som PVS havde lært at analysere under Linux, og besluttede at prøve den på mine egne projekter. Og det er det, der kom ud af det.
Jeg anmodede om en prøvenøgle, og de sendte den til mig samme dag.
Ganske klar dokumentation
Det lykkedes os at starte analysatoren uden problemer. Hjælp til konsolkommandoer er også tilgængelig (selvom der er nogle klager her, se afsnittet Cons).
Mulighed for flertrådsanalyse
Analysatoren har en "standard" mulighed -j, hvilket gør det muligt at udføre analyser parallelt i flere opgaver. Dette sparer meget tid.
Al dokumentation er på deres hjemmeside, jeg kan kun sige, at hvis dit projekt er bygget ved hjælp af CMake, så er alt meget enkelt.
Gode diagnostiske beskrivelser
Hvis du genererer output i mode fullhtml, så har hver besked et link til en diagnostisk beskrivelse med forklaringer, kodeeksempler og yderligere links.
Desværre laver PVS nogle gange syntaksfejl og genererer falske positive beskeder, når koden er helt korrekt.
For eksempel er der en funktion, der returnerer 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 er nøgleordet auto Kan betyde void, det er det, det er til auto. Men PVS producerede følgende meddelelser:
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.
Meget langsom side
Ja, i webgrænsefladen ved siden af hver besked er der et link til den tilsvarende diagnostiske beskrivelse med eksempler. Men når du klikker på et link, skal du vente ret lang tid, og nogle gange sker det 504 Gateway Timeout.
Sprog
Alle beskrivelser er på russisk, hvilket er fantastisk. Men links fra rapporten fører altid til den engelske version. Det ville være rart at kunne skifte sprog, så du straks kan se diagnostik på russisk. Jeg fandt ikke en sådan mulighed i grænsefladen.
Det er ubelejligt at arbejde med diagnostiske niveauer via konsollen
Lad os starte med det faktum, at de to brugte kommandoer (dette pvs-studio-analyzer и plog-converter) forskellige formater til angivelse af diagnostik.
Hjælp til pvs-studio-analyzer lyder:
-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
Jeg brugte lang tid på at finde ud af, hvor jeg skulle hen tilføje (“tilføje værdierne”) nøgler. Jeg forsøgte at angive dem adskilt med kommaer:
pvs-studio-analyzer analyze ... -a 1,4,16
Jeg forsøgte at registrere nøglen flere gange:
pvs-studio-analyzer analyze ... -a 1 -a 4 -a 16
Og først da indså jeg, at det var bitmasker! Og du har brug for sammenfatteOg ikke tilføje betydninger. For at få generel diagnostik, diagnostik til mikrooptimeringer og MISRA, skal du for eksempel opsummere dem (4 + 8 + 32 = 44):
pvs-studio-analyzer analyze ... -a 44
Brug af bitmasker i brugergrænseflader er generelt dårlig form. Alt dette kunne opsummeres internt, og et sæt flag kunne indstilles til brugeren.
Derudover er der også et værktøj plog-converter, som genererer statisk analyseinformation, der kan læses af mennesker. Hun har andre problemer.
Hjælp til programmet plog-converter rapporter:
-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
Der dukkede nogle "niveauer" op her, som ikke var der før, og jeg fandt heller ikke noget om dem i dokumentationen.
Generelt er det ikke klart. Derfor sætter jeg alt til det maksimale.
En flok dumme bande på Catch
To af de tre projekter, jeg analyserede, bruger et enhedstestbibliotek Catch2. Og broderparten af beskeder (!!! 90 ud af 138 i den ene og 297 ud af 344 i den anden!!!) har følgende form:
Tager ikke højde for multithreading
Der er mange falske positiver om angiveligt uforanderlige variabler eller endeløse loops, mens arbejdet med disse variable foregår fra forskellige tråde, og hvis dette ikke var tilfældet, ville enhedstest ikke fungere.
Men kan en statisk analysator overhovedet tage højde for dette? Ved ikke.
PVS fandt ingen rigtige fejl i mine open source-projekter Burst и Næste, samt i et arbejdsudkast, som jeg af indlysende grunde ikke kan fremlægge. Sandt nok er det værd at huske på, at nogle mangler allerede er blevet fanget og rettet tidligere ved brug Cppcheck и scan-build.
Generelt er indtrykket fra alle disse analysatorer omtrent det samme: ja, de fanger noget, nogle gange endda noget vigtigt, men overordnet er compileren nok.
Det er muligt (og jeg personligt kan lide at tro det), at vores team bruger softwareudviklingspraksis, der tillader os at generere et minimum af lortekode. Det er bedre ikke at skabe problemer end at heroisk overvinde dem.
Derfor tillader jeg mig at give nogle råd til, hvordan man skriver i C++ på en sådan måde, at man ikke skyder nogens ben af eller slår nogen i panden med en rive.
Få mest muligt ud af compilerdiagnostik
Vores team bruger (og råder dig til) følgende kompileringsmuligheder:
Aktiver dem i dit projekt, og lær meget om din kode.
Hold dig til standarden
Prøv ikke at bruge platformsafhængige ting, hvis der er standardanaloger, og hvis du absolut ikke kan undvære dem, så pak dem ind i specielle blokke til makroer (eller noget andet) og lad simpelthen ikke din kode kompileres under ikke-understøttede forhold.
Hold dig til standard operation semantik
Tilføjelse skal være addition, multiplikation skal være multiplikation, funktionskald skal være funktionskald, kopi skal være kopi, carry skal være carry, container skal kunne itereres, iterator skal have forfremmelse ++ og dereference *. Og så videre og så videre.
Jeg synes, ideen er klar. Der er etablerede konventioner, som ikke er bindende, men som alle brugere og læsere af din kode forventer at se. Forsøg ikke at overliste andre, ellers vil du overliste dig selv.
Skriv kompatibel kode
Først og fremmest mener jeg standardbiblioteket. Det er yderst ønskeligt, at grænsefladerne til dine klasser og funktioner kan bruges med standardbiblioteker og andre biblioteker (f.eks. Boost).
Tag gerne et kig på STL- og Boost-grænsefladerne. Med sjældne undtagelser vil du se en værdig rollemodel der.
Få mest muligt ud af open source-værktøjer
Til den samme statiske analyse er der mindst to åbne gratis værktøjer, der kun kan tilsluttes én gang til ethvert projekt med CMake-byggesystemet.
Til sidst vil jeg gerne understrege, at jeg ikke går ind for ikke at bruge PVS eller andre statiske analysatorer. Men jeg opfordrer dig til at tænke over, hvordan det skete, at den statiske analysator konstant finder væsentlige fejl i din kode.
Dette er blot en konsekvens. Vi er nødt til at lede efter og fjerne årsagen.