Unsere Aufmerksamkeit wurde auf das Electronic Arts Repository auf GitHub gelenkt. Es ist sehr klein und von 23 Projekten waren wir nur an einigen C ++ - Bibliotheken interessiert: EASTL, EAStdC, EABase, EAThread, EATest, EAMain und EAAssert. Die Projekte waren auch sehr klein (ungefähr 10 Dateien), so dass wir Fehler nur in der „größten“ von 20 Dateien fanden: D Aber wir fanden auch interessante! Während des Schreibens des Artikels diskutierten meine Kollegen und ich auch intensiv über die Spiele und die Strategie von EA: D.
Einführung
Electronic Arts (EA) ist ein amerikanisches Unternehmen, das Videospiele vertreibt. Auf der GitHub-Website hat sie ein kleines
Repository und mehrere C ++ - Projekte. Dies sind C ++ - Bibliotheken: EASTL, EAStdC, EABase, EAThread, EATest, EAMain und EAAssert. Sie sind sehr klein und wir haben interessante Fehler bei der Verwendung des
PVS-Studio- Analysators nur in der "größten" von ihnen gefunden -
EAStdC (20 Dateien). Bei solchen Volumes ist
es schwierig, über die Qualität des gesamten Codes
zu sprechen. Bewerten Sie einfach 5 Warnungen und entscheiden Sie selbst.
Warnung 1
V524 Es ist seltsam, dass der Körper der Funktion '>>' dem Körper der Funktion '<<' vollständig entspricht. EAFixedPoint.h 287
template <class T, int upShiftInt, int downShiftInt, int upMulInt, int downDivInt> struct FPTemplate { .... FPTemplate operator<<(int numBits) const { return value << numBits; } FPTemplate operator>>(int numBits) const { return value << numBits; } FPTemplate& operator<<=(int numBits) { value <<= numBits; return *this;} FPTemplate& operator>>=(int numBits) { value >>= numBits; return *this;} .... }
Beim Überladen von Schichtoperatoren machte der Programmierer einen Tippfehler in einem von ihnen und verwirrte die Operatoren << und >>. Dies ist höchstwahrscheinlich das Ergebnis der Copy-Paste-Programmierung.
Warnung 2
V557 Array-Überlauf ist möglich. Der Wert des Index 'nFormatLength' könnte 16 erreichen. EASprintfOrdered.cpp 246
static const int kSpanFormatCapacity = 16; struct Span8 { .... char mFormat[kSpanFormatCapacity]; .... }; static int OVprintfCore(....) { .... EA_ASSERT(nFormatLength < kSpanFormatCapacity); if(nFormatLength < kSpanFormatCapacity) spans[spanIndex].mFormat[nFormatLength++] = *p;
Das
Array spans [spanIndex] .mFormat besteht aus
16 Elementen, d.h. Das letzte gültige Element hat einen Index von
15 . Jetzt wird der
OVprintfCore- Funktionscode so geschrieben, dass, wenn der
nFormatLength- Index den maximal möglichen Index -
15 hat , ein Inkrement von bis zu
16 auftritt. Weiter in der
switch-Anweisung ist es möglich, über die Grenze des Arrays hinauszugehen.
Dieses Codefragment wurde an zwei weitere Stellen kopiert:
- V557 Array-Überlauf ist möglich. Der Wert des Index 'nFormatLength' könnte 16 erreichen. EASprintfOrdered.cpp 614
- V557 Array-Überlauf ist möglich. Der Wert des Index 'nFormatLength' könnte 16 erreichen. EASprintfOrdered.cpp 977
Warnung 3
V560 Ein Teil des bedingten Ausdrucks ist immer wahr: (Ergebnis> = 0). EASprintfOrdered.cpp 489
static int OVprintfCore(....) { .... for(result = 1; (result >= 0) && (p < pEnd); ++p) { if(pWriteFunction8(p, 1, pWriteFunctionContext8, kWFSIntermediate) < 0) return -1; nWriteCountSum += result; } .... }
Das Bedingungsergebnis
> = 0 ist immer wahr, da sich die
Ergebnisvariable an keiner Stelle in der Schleife ändert. Der Code sieht sehr verdächtig aus und höchstwahrscheinlich liegt ein Fehler in diesem Code vor.
Dieses Codefragment wurde an zwei weitere Stellen kopiert:
- V560 Ein Teil des bedingten Ausdrucks ist immer wahr: (Ergebnis> = 0). EASprintfOrdered.cpp 852
- V560 Ein Teil des bedingten Ausdrucks ist immer wahr: (Ergebnis> = 0). EASprintfOrdered.cpp 1215
Warnung 4
V1009 Überprüfen Sie die Array-Initialisierung. Nur das erste Element wird explizit initialisiert. Die restlichen Elemente werden mit Nullen initialisiert. EASprintfOrdered.cpp 151
static int OVprintfCore(....) { .... int spanArgOrder[kArgCapacity] = { -1 }; .... }
Dies ist möglicherweise kein Fehler, aber Entwickler sollten gewarnt werden, dass nur das erste Element des
spanArgOrder- Arrays mit dem Wert
-1 initialisiert wird und alle anderen den Wert 0 haben.
Dieses Codefragment wurde an zwei weitere Stellen kopiert:
- V1009 Überprüfen Sie die Array-Initialisierung. Nur das erste Element wird explizit initialisiert. Die restlichen Elemente werden mit Nullen initialisiert. EASprintfOrdered.cpp 518
- V1009 Überprüfen Sie die Array-Initialisierung. Nur das erste Element wird explizit initialisiert. Die restlichen Elemente werden mit Nullen initialisiert. EASprintfOrdered.cpp 881
Warnung 5
V728 Eine übermäßige Überprüfung kann vereinfacht werden. Das '(A &&! B) || (! A && B) 'Ausdruck entspricht dem Ausdruck' bool (A)! = Bool (B) '. int128.h 1242
inline void int128_t::Modulus(....) const { .... bool bDividendNegative = false; bool bDivisorNegative = false; .... if( (bDividendNegative && !bDivisorNegative) || (!bDividendNegative && bDivisorNegative)) { quotient.Negate(); } .... }
Dieses Codefragment wurde der Einfachheit halber formatiert, aber im Original ist es eine sehr lange Bedingung, die schwer zu lesen ist. Eine andere Sache ist, wenn wir den bedingten Ausdruck vereinfachen, wie der Analysator empfiehlt:
if( bDividendNegative != bDivisorNegative) { quotient.Negate(); }
Der Code ist viel kürzer geworden, was das Verständnis der Logik des bedingten Ausdrucks erheblich vereinfacht hat.
Fazit
Wie Sie vielleicht bemerkt haben, werden die meisten verdächtigen Warnungen an drei Stellen und in derselben Datei dupliziert. Die Vervielfältigung von Code ist eine sehr schlechte Entwicklungspraxis erschwert die Codeunterstützung. Und wenn in einem solchen Code ein Fehler auftritt, nimmt die Stabilität des Programms aufgrund der Verteilung von Fehlern im gesamten Code stark ab.
Hoffen wir, dass noch etwas Interessantes veröffentlicht wird und wir wieder in dieses Repository zurückkehren :). In der Zwischenzeit schlage ich diejenigen vor, die
PVS-Studio herunterladen und versuchen möchten, ihre eigenen Projekte zu überprüfen.

Wenn Sie diesen Artikel einem englischsprachigen Publikum zugänglich machen möchten, verwenden Sie bitte den Link zur Übersetzung: Svyatoslav Razmyslov.
Fast perfekte Bibliotheken von Electronic Arts .