Ich sah eine Veröffentlichung, deren Analyse PVS unter Linux gelernt hatte, und beschloss, sie in meinen eigenen Projekten auszuprobieren. Und das ist dabei herausgekommen.
Ich habe einen Testschlüssel angefordert und sie haben ihn mir noch am selben Tag zugesandt.
Ziemlich klare Dokumentation
Es ist uns gelungen, den Analysator ohne Probleme zu starten. Hilfe für Konsolenbefehle ist ebenfalls verfügbar (obwohl es hier einige Beschwerden gibt, siehe Abschnitt Cons).
Möglichkeit der Multithread-Analyse
Der Analysator verfügt über eine „Standard“-Option -j, sodass die Analyse in mehreren Aufgaben parallel durchgeführt werden kann. Das spart viel Zeit.
Die gesamte Dokumentation befindet sich auf ihrer Website. Ich kann nur sagen, dass alles sehr einfach ist, wenn Ihr Projekt mit CMake erstellt wird.
Gute Diagnosebeschreibungen
Wenn Sie eine Ausgabe im Modus generieren fullhtml, dann verfügt jede Nachricht über einen Link zu einer Diagnosebeschreibung mit Erläuterungen, Codebeispielen und zusätzlichen Links.
Leider macht PVS manchmal Syntaxfehler und generiert falsch positive Meldungen, wenn der Code vollständig korrekt ist.
Es gibt zum Beispiel eine Funktion, die zurückgibt 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, Stichwort auto Kann bedeuten void, dafür ist es da Auto. Aber PVS produzierte die folgenden Meldungen:
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.
Sehr langsame Seite
Ja, im Webinterface gibt es neben jeder Meldung einen Link zur entsprechenden Diagnosebeschreibung mit Beispielen. Aber wenn man auf einen Link klickt, muss man ziemlich lange warten, und manchmal passiert es 504 Gateway-Time-out.
Sprache
Alle Beschreibungen sind auf Russisch, was großartig ist. Links aus dem Bericht führen jedoch immer zur englischen Version. Es wäre schön, die Sprache umstellen zu können, damit Sie die Diagnose sofort auf Russisch anzeigen können. Eine solche Option habe ich in der Benutzeroberfläche nicht gefunden.
Das Arbeiten mit Diagnoseebenen über die Konsole ist umständlich
Beginnen wir mit der Tatsache, dass die beiden verwendeten Befehle (dies pvs-studio-analyzer и plog-converter) verschiedene Formate zur Angabe der Diagnose.
Hilfe für pvs-studio-analyzer lautet:
-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
Ich habe lange darüber nachgedacht, wohin ich gehen soll addieren („Werte hinzufügen“). Ich habe versucht, sie durch Kommas getrennt aufzulisten:
pvs-studio-analyzer analyze ... -a 1,4,16
Ich habe mehrmals versucht, den Schlüssel zu registrieren:
pvs-studio-analyzer analyze ... -a 1 -a 4 -a 16
Und erst dann wurde mir klar, dass es sich um Bitmasken handelte! Und du brauchst zusammenfassenUnd nicht addieren Bedeutungen. Um beispielsweise allgemeine Diagnosen, Diagnosen für Mikrooptimierungen und MISRA zu erhalten, müssen Sie diese zusammenfassen (4 + 8 + 32 = 44):
pvs-studio-analyzer analyze ... -a 44
Die Verwendung von Bitmasken in Benutzeroberflächen ist im Allgemeinen eine schlechte Form. All dies könnte intern zusammengefasst werden und eine Reihe von Flags könnten für den Benutzer gesetzt werden.
Darüber hinaus gibt es auch ein Dienstprogramm plog-converter, das für Menschen lesbare statische Analyseinformationen generiert. Sie hat andere Probleme.
Hilfe zum Programm plog-converter Berichte:
-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 sind einige „Level“ aufgetaucht, die vorher nicht da waren, und auch in der Dokumentation habe ich nichts darüber gefunden.
Im Allgemeinen ist es nicht klar. Deshalb habe ich alles auf Maximum gestellt.
Ein Haufen dummer Beschimpfungen auf Catch
Zwei der drei von mir analysierten Projekte verwenden eine Unit-Testing-Bibliothek Catch2. Und der Löwenanteil der Nachrichten (!!! 90 von 138 im einen und 297 von 344 im anderen!!!) hat die folgende Form:
Multithreading wird nicht berücksichtigt
Es gibt viele Fehlalarme über vermeintlich unveränderliche Variablen oder Endlosschleifen, während die Arbeit mit diesen Variablen von verschiedenen Threads aus erfolgt, und wenn dies nicht der Fall wäre, würden Unit-Tests nicht funktionieren.
Kann ein statischer Analysator dies jedoch überhaupt berücksichtigen? Weiß nicht.
PVS hat in meinen Open-Source-Projekten keine echten Fehler gefunden Burst и Proximasowie in einem Arbeitsentwurf, den ich aus offensichtlichen Gründen nicht vorlegen kann. Es ist allerdings zu bedenken, dass einige Mängel bereits früher erkannt und behoben wurden Cppcheck и scan-build.
Im Allgemeinen ist der Eindruck aller dieser Analysatoren ungefähr der gleiche: Ja, sie fangen etwas, manchmal sogar etwas Wichtiges, aber im Großen und Ganzen reicht der Compiler aus.
Es ist möglich (und ich persönlich denke das gerne), dass unser Team Softwareentwicklungspraktiken verwendet, die es uns ermöglichen, ein Minimum an beschissenem Code zu generieren. Es ist besser, keine Probleme zu schaffen, als sie heldenhaft zu überwinden.
Daher erlaube ich mir, einige Ratschläge zu geben, wie man in C++ so schreibt, dass man niemandem die Beine abschießt oder jemandem mit einem Rechen auf die Stirn schlägt.
Machen Sie das Beste aus der Compiler-Diagnose
Unser Team nutzt (und empfiehlt Ihnen) folgende Zusammenstellungsmöglichkeiten:
Aktivieren Sie sie in Ihrem Projekt und erfahren Sie viel über Ihren Code.
Bleiben Sie beim Standard
Versuchen Sie, keine plattformabhängigen Dinge zu verwenden, wenn es Standardanaloga gibt, und wenn Sie absolut nicht darauf verzichten können, packen Sie sie in spezielle Blöcke für Makros (oder etwas anderes) ein und lassen Sie Ihren Code einfach nicht unter nicht unterstützten Bedingungen kompilieren.
Halten Sie sich an die Standardoperationssemantik
Addition muss Addition sein, Multiplikation muss Multiplikation sein, Funktionsaufruf muss Funktionsaufruf sein, Kopie muss Kopie sein, Übertrag muss Übertrag sein, Container muss iterierbar sein, Iterator muss hochgestuft sein ++ und Dereferenzierung *. Und so weiter und so fort.
Ich denke, die Idee ist klar. Es gibt etablierte Konventionen, die nicht verbindlich sind, die aber von allen Benutzern und Lesern Ihres Codes erwartet werden. Versuchen Sie nicht, andere zu überlisten, sonst überlisten Sie sich selbst.
Schreiben Sie kompatiblen Code
Zunächst einmal meine ich die Standardbibliothek. Es ist äußerst wünschenswert, dass die Schnittstellen Ihrer Klassen und Funktionen mit Standard- und anderen Bibliotheken (z. B. Boost) verwendet werden können.
Werfen Sie gerne einen Blick auf die STL- und Boost-Schnittstellen. Von seltenen Ausnahmen abgesehen findet man dort ein würdiges Vorbild.
Machen Sie das Beste aus Open-Source-Tools
Für die gleiche statische Analyse gibt es mindestens zwei offene kostenlose Tools, die nur einmal mit jedem Projekt mit dem CMake-Build-System verbunden werden können.
Abschließend möchte ich betonen, dass ich nicht dafür plädiere, PVS oder andere statische Analysegeräte nicht zu verwenden. Aber ich ermutige Sie, darüber nachzudenken, wie es dazu kam, dass der statische Analysator ständig erhebliche Fehler in Ihrem Code findet.
Das ist nur eine Konsequenz. Wir müssen die Ursache suchen und beseitigen.