
Es war geplant, dass wir, nachdem wir den Artikel "Es ist eine Schande für Meinungen über statische Code-Analysatoren" geschrieben haben, das Thema aussprechen und ruhig loslassen werden. Aber unerwartet löste dieser Artikel eine stürmische Reaktion aus. Leider ist die Diskussion schief gelaufen, und jetzt werden wir einen zweiten Versuch unternehmen, unsere Vision der Situation zu erklären.
Anekdoten-Analogie
Alles begann mit dem Artikel " Es ist eine Schande für Meinungen über statische Code-Analysatoren ". Es wurde begonnen, aktiv über einige Ressourcen zu diskutieren, und diese Diskussion ist der folgenden alten Anekdote sehr ähnlich.
Wir haben eine japanische Kettensäge für einige harte sibirische Holzfäller gekauft.Eins zu eins Geschichte. Die Leute sahen sich den Code an:
Die Holzfäller versammelten sich im Kreis und beschlossen, es zu testen.
Sie brachten sie herein, gaben ihr einen Baum.
"Reißverschluss", sagte der Japaner.
"Oh, verdammt ..." - sagten die Holzfäller.
Sie gaben ihr einen dickeren Baum. "Vzh-g-zhik!" - sagte die Säge.
"Wow, verdammt!" - sagten die Holzfäller.
Sie steckten eine dicke Zeder in sie. "VZH-ZH-ZH-ZH-ZH-ZH-ZHIK !!!" - sagte die Säge.
"Wow, verdammt !!" - sagten die Holzfäller.
Sie gaben ihr ein Stück Eisen. "RISS!" - sagte die Säge.
"Ja, verdammt !!!" - Stern Sibirische Holzfäller sagten vorwurfsvoll! Und sie gingen, um den Wald mit Äxten zu fällen ...
if (A[0] == 0)
{
X = Y;
if (A[0] == 0)
....
}
Und sie begannen Situationen zu erfinden, in denen dies gerechtfertigt sein könnte, was bedeutet, dass die Warnung des PVS-Studio-Analysators falsch positiv ist. Die Argumentation ging in den Kurs über die Änderung des Gedächtnisses zwischen zwei Überprüfungen ein, die sich ergeben aus:
- Arbeit von parallelen Strömen;
- Signal- / Interrupt-Handler;
- Variable X ist eine Referenz auf Element A [0] ;
- Hardware, wie das Durchführen von DMA-Operationen;
- usw.
Und nachdem sie besprochen hatten, dass nicht alle Situationen der Analysator verstehen kann, gingen sie, um den Wald mit Äxten zu fällen. Das heißt, wir haben eine Entschuldigung gefunden, warum es möglich ist, den statischen Code-Analysator in unserer Arbeit weiterhin nicht zu verwenden.
Unsere Vision der Situation
Dieser Ansatz ist kontraproduktiv. Ein unvollkommenes Werkzeug mag nützlich sein, aber seine Verwendung ist wirtschaftlich.
Ja, jeder statische Analysator erzeugt falsch positive Ergebnisse. Und nichts kann dagegen unternommen werden. Dieses Unglück ist jedoch stark übertrieben. In der Praxis können statische Analysegeräte auf verschiedene Weise konfiguriert und verwendet werden, um Fehlalarme zu unterdrücken und damit zu arbeiten (siehe 1 , 2 , 3 , 4 ). Außerdem ist es angebracht, hier an den Artikel " False Positives sind unsere Feinde, aber möglicherweise immer noch Ihre Freunde " zu erinnern .
Aber auch das ist nicht die Hauptsache. Es macht keinen Sinn, spezielle Fälle von exotischem Code überhaupt zu berücksichtigen!Können Sie den Analysator mit einem komplexen Code verwechseln? Ja, du kannst. In einem solchen Fall gibt es jedoch Hunderte nützlicher Analysatorauslöser. Viele Fehler können sehr früh gefunden und korrigiert werden. Ein oder zwei Fehlalarme können sicher unterdrückt werden und werden nicht mehr beachtet.
Und wieder ist PVS-Studio richtig
Hier könnte der Artikel fertiggestellt werden. Einige mögen den vorherigen Abschnitt jedoch nicht als rationale Überlegungen betrachten, sondern versuchen, die Schwächen und Mängel des PVS-Studio-Tools zu verbergen. Also musst du weitermachen.
Betrachten Sie konkreten kompilierten Code , der Variablendeklarationen enthält:
void SetSynchronizeVar(int *);
int foo()
{
int flag = 0;
SetSynchronizeVar(&flag);
int X, Y = 1;
if (flag == 0)
{
X = Y;
if (flag == 0)
return 1;
}
return 2;
}
Der PVS-Studio-Analysator gibt vernünftigerweise eine Warnung aus: V547 Ausdruck 'flag == 0' ist immer wahr.
Und der Analysator ist absolut richtig. Wenn jemand anfängt zu schimpfen, dass sich eine Variable in einem anderen Thread, in einem Signalhandler usw. ändern kann, versteht er die Sprachen C und C ++ einfach nicht. So kann man nicht schreiben.
Zu Optimierungszwecken hat der Compiler das Recht, die zweite Prüfung zu verwerfen, und ist absolut richtig. Aus sprachlicher Sicht kann sich eine Variable nicht ändern. Die Hintergrundänderung ist nichts anderes als undefiniertes Verhalten.
Damit die Prüfung bestehen bleibt, muss die Variable als flüchtig deklariert werden :
void SetSynchronizeVar(volatile int *);
int foo()
{
volatile int flag = 0;
SetSynchronizeVar(&flag);
....
}
Der PVS-Studio-Analysator weiß davon und gibt keine Warnung mehr für einen solchen Code aus .
Hier kehren wir zu dem zurück, was im ersten Artikel besprochen wurde . Es gibt kein Problem. Es gibt jedoch Kritik oder Missverständnisse, warum der Analysator das Recht hat, eine Warnung auszugeben.
Hinweis für die akribischsten Leser
Einige Leser kehren möglicherweise zum synthetischen Beispiel aus dem ersten Artikel zurück:
char get();
int foo(char *p, bool arg)
{
if (p[1] == 1)
{
if (arg)
p[0] = get();
if (p[1] == 1) // Warning
return 1;
}
// ....
return 3;
}
Und flüchtige hinzufügen :
char get();
int foo(volatile char *p, bool arg)
{
if (p[1] == 1)
{
if (arg)
p[0] = get();
if (p[1] == 1) // Warning :-(
return 1;
}
// ....
return 3;
}
Danach kann man mit Recht sagen, dass der Analysator immer noch die Warnung V547 ausgibt. Der Ausdruck 'p [1] == 1' ist immer wahr.
Hurra, es hat sich endlich gezeigt, dass der Analysator immer noch falsch ist :). Das ist falsch positiv!
Wie Sie sehen, verstecken wir keine Mängel. Beim Parsen des Datenstroms nach Array-Elementen ging dieses unglückliche flüchtige Element verloren. Der Fehler wurde bereits gefunden und behoben. Das Update wird in der nächsten Version des Analysators verfügbar sein. Es wird keine Fehlalarme geben.
Warum wurde dieser Fehler nicht früher erkannt? Denn in der Tat ist dies wieder unwirklicher Code, der in echten Projekten nicht gefunden wird. Tatsächlich sind wir bisher nicht auf solchen Code gestoßen, obwohl wir viele Open-Source-Projekte überprüft haben .
Warum ist der Code unrealistisch? Erstens wird es in der Praxis eine Art Zeit- oder Verzögerungsfunktion zwischen den beiden Überprüfungen geben. Zweitens erstellt niemand, der bei klarem Verstand ist, Arrays, die aus flüchtigen Elementen bestehen, es sei denn, dies ist absolut notwendig. Die Arbeit mit einem solchen Array ist ein kolossaler Leistungsabfall.
Fassen wir zusammen. Es ist einfach, Beispiele zu erstellen, bei denen der Parser fehlschlägt. Aus praktischer Sicht wirken sich die festgestellten Fehler jedoch praktisch nicht auf die Qualität der Code-Analyse und die Anzahl der festgestellten tatsächlichen Fehler aus. Schließlich ist der Code realer Anwendungen nur Code, der für den Analysator und die Person gleichzeitig verständlich ist, und kein Rebus oder Puzzle. Wenn der Code ein Puzzle ist, bleibt keine Zeit für Analysatoren :).
Vielen Dank für Ihre Aufmerksamkeit.

Zusätzliche Links
- So implementieren Sie einen statischen Code-Analysator in einem Legacy-Projekt und demotivieren das Team nicht .
- Zusätzliche Diagnoseeinstellungen .
- Eigenschaften des PVS-Studio-Analysators am Beispiel von EFL-Kernbibliotheken, 10-15% der falsch positiven Ergebnisse .
- Führen Sie statische Analysen in Ihren Prozess ein, anstatt nach Fehlern zu suchen .

Wenn Sie diesen Artikel einem englischsprachigen Publikum zugänglich machen möchten, verwenden Sie bitte den Übersetzungslink: Andrey Karpov. Teil 2: Aufregende Meinungen über statische Analysatoren .