PVS-Studio erzeugt wie andere statische Code-Analysatoren häufig falsch positive Ergebnisse. Aber beeilen Sie sich nicht, seltsame Antworten als falsch zu betrachten. Dies ist eine kurze Geschichte darüber, wie sich PVS-Studio erneut als aufmerksamer gegenüber mehreren Personen herausstellte.
Der Benutzer schrieb zur Unterstützung von uns und behauptete, dass der Analysator sofort vier falsch positive Ergebnisse pro Codezeile erzeugt. Der zur Unterstützung verfasste Brief ging zunächst an Jewgeni Ryzhkow, der ihn, nachdem er ihn fließend gelesen und keine ungewöhnlichen Rückmeldungen bemerkt hatte, sofort an den Hauptentwickler Svyatoslav Razmyslov schickte. Eugene hat nicht in den Code geschaut, daher wäre es fair, ihn nur für die Hälfte des Programmierers zu zählen :).
Svyatoslav las den Brief und bezweifelte, dass der Analysator so grob falsch sein könnte. Deshalb kam er zu einer Beratung zu mir. Svyatoslav hatte die Hoffnung, dass mein Auge gesetzt war und ich etwas bemerken werde, das mir sagt, warum der Analysator all diese seltsamen Nachrichten ausgegeben hat. Leider habe ich nur bestätigt, dass die Nachrichten wirklich sehr seltsam sind und nicht sein sollten. Was jedoch der Grund für ihr Auftreten war, konnte ich nicht bemerken. Es wurde beschlossen, die Aufgabe im Bugtracker zu öffnen und zu verstehen, was falsch war.
Und erst als Svyatoslav anfing, synthetische Beispiele zu erstellen, um das Problem im Bugtracker detailliert zu beschreiben, dämmerte ihm die Einsicht. Lassen Sie uns nun sehen, ob Sie schnell den Grund finden können, warum der Analysator 4 Meldungen anzeigt.
Hier ist der Text des Briefes, der mit Genehmigung des Autors veröffentlicht wurde. Und ein erklärendes Bild, das dem Brief beigefügt war.
V560-Warnungen hier sind alle falsch. Läuft mit der neuesten Version von PVS-Studio für den persönlichen Gebrauch. Grundsätzlich ist die IF-Anweisung korrekt. Das Äußere geschieht aus Gründen der Geschwindigkeit - das Innere wird immer noch benötigt und das Nicht-Wahre ist immer wahr oder falsch.
Nun, lieber Leser, Ihre Zeit, sich selbst zu testen! Sehen Sie den Fehler?
Ihre Zeit, aufmerksam zu sein. Und das Einhorn wird ein bisschen warten.
Nach dem einleitenden Teil des Artikels haben höchstwahrscheinlich viele einen Fehler gefunden. Wenn konfiguriert, um einen Fehler zu finden, befindet er sich. Es ist viel schwieriger, einen Fehler nach dem Lesen des Briefes zu bemerken, der als "falsch positiv" bezeichnet wird :).
Nun eine Erklärung für diejenigen, die zu faul sind, um nach einem Fehler zu suchen. Betrachten Sie die Bedingung noch einmal:
if (!((ch >= 0x0FF10) && (ch <= 0x0FF19)) || ((ch >= 0x0FF21) && (ch <= 0x0FF3A)) || ((ch >= 0x0FF41) && (ch <= 0x0FF5A)))
Der Autor des Codes wollte überprüfen, ob das Zeichen in einen der drei Bereiche fällt.
Der Fehler ist, dass der logische NOT-Operator (!) Nur für den ersten Unterausdruck gilt.
Wenn die Bedingung erfüllt ist:
!((ch >= 0x0FF10) && (ch <= 0x0FF19))
dann wird die Ausdrucksauswertung gemäß der
Kurzschlussauswertung unterbrochen. Wenn die Bedingung nicht erfüllt ist, liegt der Wert der Variablen
ch im Bereich [0xFF10..0xFF19]. Dementsprechend sind vier weitere Vergleiche nicht sinnvoll. Alle von ihnen werden falsch oder wahr sein.
Noch einmal. Sehen Sie, wenn
ch im Bereich
[0xFF10..0xFF19] liegt und die Berechnung fortgesetzt wird, dann:
- ch> = 0x0FF21 - immer falsch
- ch <= 0x0FF3A - immer wahr
- ch> = 0x0FF41 - immer falsch
- ch <= 0x0FF5A - immer wahr
Darum warnt der PVS-Studio-Analysator.
Der statische Analysator erwies sich als aufmerksamer als der Benutzer und zweieinhalb Programmierer aus unserem Team.
Um die Situation zu beheben, müssen Sie zusätzliche Klammern hinzufügen:
if (!(((ch >= 0x0FF10) && (ch <= 0x0FF19)) || ((ch >= 0x0FF21) && (ch <= 0x0FF3A)) || ((ch >= 0x0FF41) && (ch <= 0x0FF5A))))
Oder schreiben Sie die Bedingung neu:
if (((ch < 0x0FF10) || (ch > 0x0FF19)) && ((ch < 0x0FF21) || (ch > 0x0FF3A)) && ((ch < 0x0FF41) || (ch > 0x0FF5A)))
Ich kann jedoch keine dieser Optionen empfehlen. Ich würde dies schreiben, um das Lesen des Codes zu vereinfachen:
const bool isLetterOrDigit = (ch >= 0x0FF10 && ch <= 0x0FF19)
Beachten Sie, dass ich einige der Klammern entfernt habe. Wie wir gerade gesehen haben, hat eine große Anzahl von Klammern nicht dazu beigetragen, einen Fehler überhaupt zu vermeiden. Klammern sollten das Lesen von Code erleichtern und nicht komplizierter sein. Programmierer erinnern sich gut daran, dass die Priorität von Vergleichen = <, => höher ist als die des Operators &&. Daher werden hier keine Klammern benötigt. Wenn Sie jedoch fragen, welche Priorität && oder || ist, werden viele verwirrt. Um die Reihenfolge der Berechnungen && anzugeben, || Klammern sind besser zu setzen.
Warum ist es besser zu schreiben || Am Anfang habe ich im Artikel „
Das Hauptproblem des Programmierens, Refactorings und all das “ beschrieben (siehe Kapitel: Den gleichen Codetyp an einer „Tabelle“ ausrichten).
Vielen Dank für Ihre Aufmerksamkeit. Laden Sie
PVS-Studio herunter und starten Sie es. Es wird helfen, viele Fehler und potenzielle Schwachstellen in den frühesten Stadien zu identifizieren.

Wenn Sie diesen Artikel einem englischsprachigen Publikum zugänglich machen möchten, verwenden Sie bitte den Link zur Übersetzung: Andrey Karpov.
Wie sich PVS-Studio als aufmerksamer als dreieinhalb Programmierer erwies .