Top 10 Fehler in C ++ - Projekten für 2018

Es ist schon drei Monate her, seit 2018 vorbei ist. Für viele flog es fast unmerklich, aber für uns, die Entwickler von PVS-Studio, stellte sich heraus, dass es sehr gesättigt war. Wir haben hart gearbeitet, furchtlos für die Weiterentwicklung der statischen Analyse für die Massen gekämpft und nach neuen Fehlern in Open-Source-Projekten gesucht, die in C, C ++, C # und Java geschrieben wurden. Die zehn interessantesten davon haben wir in diesem Artikel für Sie gesammelt!



Mit dem statischen Code-Analysator PVS-Studio haben wir nach interessanten Orten gesucht. Es kann Fehler und potenzielle Schwachstellen in Code erkennen, der in den oben genannten Sprachen geschrieben wurde.

Wenn Sie selbst nach Fehlern suchen möchten, können Sie unseren Analysator jederzeit herunterladen und ausprobieren. Wir bieten eine kostenlose Version des Analysators für Studenten und begeisterte Programmierer, eine kostenlose Lizenz für Entwickler von Open-Source-Projekten sowie eine Testversion für All-All-All. Wer weiß, vielleicht können Sie bis zum nächsten Jahr Ihre Top 10 erreichen? :) :)

Hinweis: Ich schlage vor, dass der Leser sich selbst überprüft und vor dem Betrachten der Analysatorwarnung versucht, die Anomalien selbst zu identifizieren. Wie viele Fehler können Sie finden?

Zehnter Platz


Quelle: Und wieder ins All: wie das Einhorn Stellarium besuchte

Dieser Fehler wurde beim Überprüfen des virtuellen Stellarium-Planetariums entdeckt.

Das obige Code-Snippet ist zwar klein, aber mit einem ziemlich kniffligen Fehler behaftet:

Plane::Plane(Vec3f &v1, Vec3f &v2, Vec3f &v3) : distance(0.0f), sDistance(0.0f) { Plane(v1, v2, v3, SPolygon::CCW); } 

Hast du gefunden?

PVS-Studio Warnung: V603 Das Objekt wurde erstellt, wird jedoch nicht verwendet. Wenn Sie den Konstruktor aufrufen möchten, sollte 'this-> Plane :: Plane (....)' verwendet werden. Plane.cpp 29

Der Autor des Codes wollte einen Teil der Felder des Objekts mit einem anderen Konstruktor initialisieren, der im Hauptkonstruktor verschachtelt ist. Es ist ihm jedoch nur gelungen, ein temporäres Objekt zu erstellen, das beim Verlassen seines Sichtbereichs zerstört wird. Somit bleiben mehrere Felder des Objekts nicht initialisiert.

Anstelle eines verschachtelten Konstruktoraufrufs sollten Sie den in C ++ 11 eingeführten delegierenden Konstruktor verwenden. Zum Beispiel könnten Sie dies tun:

 Plane::Plane(Vec3f& v1, Vec3f& v2, Vec3f& v3) : Plane(v1, v2, v3, SPolygon::CCW) { distance = 0.0f; sDistance = 0.0f; } 

Dann würden alle erforderlichen Felder korrekt initialisiert. Ist es nicht wunderbar?

Neunter Platz


Quelle: Perl 5: Wie sich Makrofehler versteckten

Auf dem neunten Platz wird ein bemerkenswertes Makro aus dem Perl 5-Quellcode zur Schau gestellt.

Als mein Kollege Svyatoslav Fehler beim Schreiben des Artikels sammelte, stieß er auf eine Warnung des Analysators zur Verwendung eines Makros. Hier ist es:

 PP(pp_match) { .... MgBYTEPOS_set(mg, TARG, truebase, RXp_OFFS(prog)[0].end); .... } 

Um herauszufinden, was los war, grub Svyatoslav tiefer. Er öffnete die Makrodefinition und stellte fest, dass sie mehrere weitere verschachtelte Makros enthielt, von denen einige auch verschachtelte Makros enthielten. Es war so schwer herauszufinden, dass ich eine vorverarbeitete Datei verwenden musste. Aber leider hat das nicht geholfen. Anstelle der vorherigen Codezeile entdeckte Swjatoslaw Folgendes:

 (((targ)->sv_flags & 0x00000400) && (!((targ)->sv_flags & 0x00200000) || S_sv_only_taint_gmagic(targ)) ? (mg)->mg_len = ((prog->offs)[0].end), (mg)->mg_flags |= 0x40 : ((mg)->mg_len = (((targ)->sv_flags & 0x20000000) && !__builtin_expect(((((PL_curcop)->cop_hints + 0) & 0x00000008) ? (_Bool)1 :(_Bool)0),(0))) ? (ssize_t)Perl_utf8_length( (U8 *)(truebase), (U8 *)(truebase)+((prog->offs)[0].end)) : (ssize_t)((prog->offs)[0].end), (mg)->mg_flags &= ~0x40)); 

Warnung PVS-Studio: V502 Möglicherweise funktioniert der Operator '?:' Anders als erwartet. Der Operator '?:' Hat eine niedrigere Priorität als der Operator '&&'. pp_hot.c 3036

Ich denke, es wird schwierig sein, einen solchen Fehler mit meinen Augen zu finden. Ehrlich gesagt haben wir lange über diesen Code meditiert und sind zu dem Schluss gekommen, dass hier tatsächlich kein Fehler vorliegt. In jedem Fall ist dies jedoch ein unterhaltsames Beispiel für unlesbaren Code.

Makros sollen böse sein. Natürlich gibt es Zeiten, in denen sie sich als unverzichtbar herausstellen, aber wenn Sie das Makro durch eine Funktion ersetzen können, sollten Sie dies auf jeden Fall tun.

Verschachtelte Makros sind besonders voll. Nicht nur, weil sie schwer zu verstehen sind, sondern auch, weil sie unvorhersehbare Ergebnisse liefern können. Wenn der Autor eines Makros versehentlich einen Fehler in einem solchen Makro macht, ist es viel schwieriger, ihn zu finden als in einer Funktion.

Achter Platz


Quelle: Chrom: Andere Fehler

Das folgende Beispiel stammt aus einer Reihe von Artikeln zur Analyse des Chromium-Projekts. Sie deckte sich in der WebRTC-Bibliothek ab.

 std::vector<SdpVideoFormat> StereoDecoderFactory::GetSupportedFormats() const { std::vector<SdpVideoFormat> formats = ....; for (const auto& format : formats) { if (cricket::CodecNamesEq(....)) { .... formats.push_back(stereo_format); } } return formats; } 

PVS-Studio Warnung: V789 CWE-672 Iteratoren für den Container 'Formate', die in der bereichsbasierten for-Schleife verwendet werden, werden beim Aufruf der Funktion 'push_back' ungültig. stereocodecfactory.cc 89

Der Fehler besteht darin, dass sich die Größe des Formatvektors innerhalb der bereichsbasierten for-Schleife ändert. Bereichsbasierte Schleifen basieren auf Iteratoren. Daher kann die Größenänderung des Containers in solchen Schleifen zur Ungültigmachung dieser Iteratoren führen.

Dieser Fehler bleibt bestehen, wenn Sie die Schleife mit expliziten Iteratoren neu schreiben. Aus Gründen der Übersichtlichkeit können Sie diesen Code daher mitbringen:

 for (auto format = begin(formats), __end = end(formats); format != __end; ++format) { if (cricket::CodecNamesEq(....)) { .... formats.push_back(stereo_format); } } 

Wenn Sie beispielsweise die push_back- Methode verwenden, wird möglicherweise ein Vektor freigegeben, und dann zeigen Iteratoren auf einen ungültigen Speicherbereich.

Um solche Fehler zu vermeiden, sollten Sie die Regel einhalten: Ändern Sie niemals die Größe des Containers innerhalb der Schleife, deren Bedingungen an diesen Container gebunden sind. Dies gilt für bereichsbasierte Schleifen und Schleifen mit Iteratoren. In Diskussionen zu StackOverflow können Sie nachlesen, welche Vorgänge zur Ungültigmachung von Iteratoren führen können.

Siebter Platz


Quelle: Godot: Regelmäßige Verwendung von Static Code Analyzers

Das erste Beispiel aus der Videospielbranche wird ein Codeausschnitt sein, den wir in der Godot-Spiele-Engine entdeckt haben. Sie müssen vielleicht schwitzen, um den Fehler mit Ihren Augen zu entdecken, aber ich bin sicher, dass unsere erfahrenen Leser damit umgehen können:

 void AnimationNodeBlendSpace1D::add_blend_point( const Ref<AnimationRootNode> &p_node, float p_position, int p_at_index) { ERR_FAIL_COND(blend_points_used >= MAX_BLEND_POINTS); ERR_FAIL_COND(p_node.is_null()); ERR_FAIL_COND(p_at_index < -1 || p_at_index > blend_points_used); if (p_at_index == -1 || p_at_index == blend_points_used) { p_at_index = blend_points_used; } else { for (int i = blend_points_used - 1; i > p_at_index; i++) { blend_points[i] = blend_points[i - 1]; } } .... } 

PVS-Studio Warnung: V621 CWE-835 Überprüfen Sie den ' for' - Operator. Es ist möglich, dass die Schleife falsch oder gar nicht ausgeführt wird. animation_blend_space_1d.cpp 113

Betrachten wir den Zustand des Zyklus genauer. Die Zählervariable wird mit dem Wert blend_points_used - 1 initialisiert. Gleichzeitig wird anhand der beiden vorherigen Überprüfungen (in ERR_FAIL_COND und in if ) klar, dass zum Zeitpunkt der Ausführung der Schleife blend_points_used immer größer als p_at_index ist . Somit ist entweder die Schleifenbedingung immer wahr oder die Schleife wird überhaupt nicht ausgeführt.

Wenn blend_points_used 1 == p_at_index ist , wird die Schleife nicht ausgeführt.

In allen anderen Fällen ist die Prüfung i> p_at_index immer wahr, da der Zähler i bei jeder Iteration der Schleife zunimmt.

Es mag scheinen, dass der Zyklus für immer laufen wird, aber es ist nicht so.

Erstens wird es einen ganzzahligen Überlauf der Variablen i geben , was ein undefiniertes Verhalten ist. Verlassen Sie sich daher darauf, dass es sich nicht lohnt.

Wenn ich vom Typ unsigned int wäre, würde der i ++ - Operator den Zähler in 0 umwandeln , nachdem er den maximal möglichen Wert erreicht hat. Dieses Verhalten wird vom Standard definiert und als "vorzeichenlose Umhüllung" bezeichnet. Sie sollten sich jedoch bewusst sein, dass die Verwendung eines solchen Mechanismus ebenfalls keine gute Idee ist .

Das war erstens, aber es gibt noch zweitens! Tatsache ist, dass es nicht einmal den ganzzahligen Überlauf erreicht. Wohin geht das Array ins Ausland? Dies bedeutet, dass versucht wird, auf den Speicherbereich außerhalb des für das Array zugewiesenen Blocks zuzugreifen. Und auch dies ist ein vages Verhalten. Klassisches Beispiel :)

Um solche Fehler leichter vermeiden zu können, kann ich nur einige Empfehlungen geben:

  1. Schreiben Sie einfacheren, intuitiveren Code
  2. Führen Sie eine gründlichere Codeüberprüfung durch und schreiben Sie weitere Tests für frisch geschriebenen Code
  3. Verwenden Sie statische Analysegeräte;)


Sechster Platz


Quelle: Amazon Lumberyard: Der Schrei der Seele

Ein weiteres Beispiel aus der Gamedev-Branche, nämlich aus dem Quellcode der Amazon Lumberyard AAA-Engine.

 void TranslateVariableNameByOperandType(....) { // Igor: yet another Qualcomm's special case // GLSL compiler thinks that -2147483648 is // an integer overflow which is not if (*((int*)(&psOperand->afImmediates[0])) == 2147483648) { bformata(glsl, "-2147483647-1"); } else { // Igor: this is expected to fix // paranoid compiler checks such as Qualcomm's if (*((unsigned int*)(&psOperand->afImmediates[0])) >= 2147483648) { bformata(glsl, "%d", *((int*)(&psOperand->afImmediates[0]))); } else { bformata(glsl, "%d", *((int*)(&psOperand->afImmediates[0]))); } } bcatcstr(glsl, ")"); .... } 

PVS-Studio Warnung: V523 Die Anweisung 'then' entspricht der Anweisung 'else'. toglsloperand.c 700

Amazon Lumberyard wird als plattformübergreifende Engine entwickelt. Daher versuchen Entwickler, so viele Compiler wie möglich zu unterstützen. Der Programmierer Igor ist auf den Qualcomm-Compiler gestoßen, wie die Kommentare zeigen.

Es ist nicht bekannt, ob Igor seine Aufgabe erfüllen und die "paranoiden" Überprüfungen des Compilers bewältigen konnte, aber er hinterließ einen sehr seltsamen Code. Es ist insofern seltsam, als sowohl die damaligen als auch die anderen Zweige der if-Anweisung absolut identischen Code enthalten. Höchstwahrscheinlich wurde ein solcher Fehler durch ein schlampiges Kopieren und Einfügen verursacht.

Ich weiß nicht einmal, was hier empfohlen werden kann. Daher wünsche ich den Entwicklern von Amazon Lumberyard viel Erfolg bei der Behebung von Fehlern und viel Glück für Programmierer Igor!

Fünfter Platz


Quelle: Der PVS-Studio-Analysator erwies sich erneut als aufmerksamer als eine Person

Eine interessante Geschichte ereignete sich mit dem folgenden Beispiel. Mein Kollege Andrei Karpov bereitete einen Artikel über den nächsten Test des Qt-Frameworks vor. Während er bemerkenswerte Fehler schrieb, stieß er auf eine Analysatorwarnung, die er als falsch betrachtete. Hier ist das relevante Code-Snippet und die Warnung:

 QWindowsCursor::CursorState QWindowsCursor::cursorState() { enum { cursorShowing = 0x1, cursorSuppressed = 0x2 }; CURSORINFO cursorInfo; cursorInfo.cbSize = sizeof(CURSORINFO); if (GetCursorInfo(&cursorInfo)) { if (cursorInfo.flags & CursorShowing) // <= V616 .... } 

PVS-Studio Warnung: V616 CWE-480 Die benannte Konstante 'CursorShowing' mit dem Wert 0 wird in der bitweisen Operation verwendet. qwindowscursor.cpp 669

Das heißt, PVS-Studio hat an einem Ort geschworen, an dem offensichtlich kein Fehler aufgetreten ist! Es kann nicht sein, dass die CursorShowing- Konstante 0 ist , da buchstäblich ein paar Zeilen darüber auf 1 initialisiert werden.

Da zur Überprüfung eine instabile Version des Analysators verwendet wurde, bezweifelte Andrei die Richtigkeit der Warnung. Er untersuchte diesen Codeabschnitt mehrmals sorgfältig und fand immer noch keinen Fehler. Infolgedessen schrieb er dieses falsche Positiv an den Bugtracker, damit andere Kollegen die Situation korrigieren konnten.

Und erst mit einer detaillierten Analyse wurde klar, dass PVS-Studio wieder aufmerksamer war als eine Person. Der Wert 0x1 wird der benannten Konstanten cursorShowing zugewiesen , und die Bitkonstantenoperation "und" beinhaltet die benannte Konstante CursorShowing . Dies sind völlig unterschiedliche Konstanten, da die erste mit einem Kleinbuchstaben und die zweite mit einem Großbuchstaben beginnt.

Der Code wird erfolgreich kompiliert, da die QWindowsCursor- Klasse wirklich eine Konstante mit diesem Namen enthält. Hier ist ihre Definition:

 class QWindowsCursor : public QPlatformCursor { public: enum CursorState { CursorShowing, CursorHidden, CursorSuppressed }; .... } 

Wenn Sie eine benannte Enum-Konstante nicht explizit zuweisen, wird sie standardmäßig initialisiert. Da CursorShowing das erste Element einer Aufzählung ist, wird es auf 0 gesetzt .

Um solche Fehler zu vermeiden, sollten Sie Entitäten keine zu ähnlichen Namen geben. Sie sollten diese Regel besonders sorgfältig befolgen, wenn diese Entitäten vom gleichen Typ sind oder implizit ineinander umgewandelt werden können. In solchen Fällen ist es in der Tat fast unmöglich, einen Fehler mit dem Auge zu erkennen, und der falsche Code wird erfolgreich kompiliert und lebt glücklich in Ihrem Projekt.

Vierter Platz


Quelle: Wir schießen in den Fuß und verarbeiten die Eingabedaten

Wir nähern uns den drei besten Finalisten, und der Fehler aus dem FreeSWITCH-Projekt ist der nächste.

 static const char *basic_gets(int *cnt) { .... int c = getchar(); if (c < 0) { if (fgets(command_buf, sizeof(command_buf) - 1, stdin) != command_buf) { break; } command_buf[strlen(command_buf)-1] = '\0'; /* remove endline */ break; } .... } 

PVS-Studio Warnung: V1010 CWE-20 Nicht aktivierte fehlerhafte Daten werden im Index 'strlen (command_buf)' verwendet.

Der Analysator warnt, dass der Ausdruck strlen (command_buf) - 1 nicht verifizierte Daten verwendet. Und wirklich: Wenn sich herausstellt, dass command_buf aus Sicht der C-Sprachzeichenfolge (die ein einzelnes Zeichen enthält - '\ 0') leer ist, gibt strlen (command_buf) 0 zurück . In diesem Fall wird command_buf [-1] aufgerufen , was ein undefiniertes Verhalten darstellt. Ärger!

Der eigentliche Saft dieses Fehlers ist nicht einmal, warum es passiert, sondern wie es passiert. Dieser Fehler ist eines dieser angenehmen Beispiele, die Sie selbst "berühren" und reproduzieren können. Sie können FreeSwitch starten, einige Aktionen ausführen, die zur Ausführung des obigen Codeabschnitts führen, und dem Programm eine leere Zeile zur Eingabe übergeben.

Infolgedessen verwandelt sich ein Arbeitsprogramm mit einem Handgriff (nein, keine eleganten Shorts ) in ein nicht funktionierendes! Details zur Reproduktion dieses Fehlers finden Sie im Quellartikel unter dem obigen Link. Im Moment werde ich jedoch ein klares Ergebnis liefern:



Denken Sie daran, dass die Eingabe alles sein kann, und Sie sollten sie immer überprüfen. Dann schwört der Analysator nicht und das Programm ist zuverlässiger.

Jetzt ist es Zeit, sich mit unseren Gewinnern zu befassen: Wir ziehen ins Finale ein!



Dritter Platz


Quelle: NCBI Genome Workbench: Gefährdete Forschung

Die drei Gewinner werden durch einen Code aus dem NCBI Genome Workbench-Projekt eröffnet - eine Reihe von Tools zum Studieren und Analysieren genetischer Daten. Obwohl es nicht notwendig ist, ein gentechnisch veränderter Übermensch zu sein, um hier einen Fehler zu finden, sind sich einige dieser Möglichkeit bewusst.

 /** * Crypt a given password using schema required for NTLMv1 authentication * @param passwd clear text domain password * @param challenge challenge data given by server * @param flags NTLM flags from server side * @param answer buffer where to store crypted password */ void tds_answer_challenge(....) { .... if (ntlm_v == 1) { .... /* with security is best be pedantic */ memset(hash, 0, sizeof(hash)); memset(passwd_buf, 0, sizeof(passwd_buf)); ... } else { .... } } 

PVS-Studio-Warnungen:

  • V597 Der Compiler könnte den Funktionsaufruf 'memset' löschen, mit dem der 'Hash'-Puffer geleert wird. Die Funktion memset_s () sollte verwendet werden, um die privaten Daten zu löschen. Challenge.c 365
  • V597 Der Compiler könnte den Funktionsaufruf 'memset' löschen, mit dem der Puffer 'passwd_buf' geleert wird. Die Funktion memset_s () sollte verwendet werden, um die privaten Daten zu löschen. Herausforderung.c 366

Haben Sie einen Fehler gefunden? Wenn ja, dann bist du - gut gemacht! .. gut oder immer noch ein gentechnisch veränderter Übermensch.

Tatsache ist, dass moderne Optimierungs-Compiler viel dazu beitragen können, dass das zusammengestellte Programm schneller funktioniert. Insbesondere können Compiler verfolgen, dass der an memset übergebene Puffer nirgendwo anders verwendet wird.

In diesem Fall können sie den „unnötigen“ Memset- Aufruf löschen und haben das Recht dazu. Dann kann ein Puffer, der wichtige Daten speichert, zur Freude der Angreifer im Speicher verbleiben.

Vor diesem Hintergrund sieht der literarische Kommentar „Mit Sicherheit ist es gut, pedantisch zu sein“ noch lustiger aus. Gemessen an der sehr geringen Anzahl von Warnungen, die für dieses Projekt ausgegeben wurden, bemühten sich die Entwickler sehr, vorsichtig zu sein und sicheren Code zu schreiben. Wie wir jedoch sehen können, ist das Überspringen dieser Sicherheitslücke sehr einfach. Gemäß der Common Weakness Enumeration wird ein Fehler als CWE-14 : Compiler-Entfernung von Code zum Löschen von Puffern klassifiziert.

Verwenden Sie die Funktion memset_s () , um die Speicherbereinigung zu löschen. Es ist nicht nur sicherer als memset () , sondern kann vom Compiler auch nicht "ignoriert" werden.

Zweiter Platz


Quelle: Wie sich herausstellte, dass PVS-Studio aufmerksamer war als dreieinhalb Programmierer

Der Silbermedaillengewinner dieses Tops wurde uns von einem unserer Kunden geschickt. Er war sich sicher, dass der Analysator falsche Warnungen erzeugte.

Eugene erhielt den Brief, scannte ihn kurz und schickte ihn an Svyatoslav. Svyatoslav betrachtete nachdenklich den vom Kunden gesendeten Codeabschnitt und dachte: "Kann der Analysator so offensichtlich falsch sein?" Deshalb hat er sich mit Andrei beraten lassen. Er überprüfte auch die Site und entschied: In der Tat gibt der Analysator falsch positive Ergebnisse aus.

Was können Sie tun, müssen Sie es beheben. Und erst als Svyatoslav anfing, synthetische Beispiele zu erstellen, um die Aufgabe als Bugtracker zu formalisieren, wurde ihm klar, was los war.

Fehler waren zwar im Code vorhanden, aber keiner der Programmierer konnte sie erkennen. Ehrlich gesagt war der Autor dieses Artikels auch nicht erfolgreich.

Und das trotz der Tatsache, dass der Analysator eindeutig Warnungen für die falschen Stellen ausgegeben hat!

Kannst du so einen schlauen Fehler finden? Testen Sie sich auf Wachsamkeit und Aufmerksamkeit.


PVS-Studio Warnung:
  • V560 Ein Teil des bedingten Ausdrucks ist immer falsch: (ch> = 0x0FF21). decodew.cpp 525
  • V560 Ein Teil des bedingten Ausdrucks ist immer wahr: (ch <= 0x0FF3A). decodew.cpp 525
  • V560 Ein Teil des bedingten Ausdrucks ist immer falsch: (ch> = 0x0FF41). decodew.cpp 525
  • V560 Ein Teil des bedingten Ausdrucks ist immer wahr: (ch <= 0x0FF5A). decodew.cpp 525

Wenn Sie Erfolg haben, werden Sie meinen Respekt nicht halten!

Der Fehler liegt in der Tatsache, dass der logische Negationsoperator (!) Nicht für die gesamte Bedingung gilt, sondern nur für ihren ersten Unterausdruck:

 !((ch >= 0x0FF10) && (ch <= 0x0FF19)) 

Wenn diese Bedingung erfüllt ist, liegt der Wert der Variablen ch im Intervall [0x0FF10 ... 0x0FF19]. Somit machen die vier weiteren Vergleiche keinen Sinn mehr: Sie werden immer entweder wahr oder falsch sein.

Um solche Fehler zu vermeiden, sollten einige Regeln beachtet werden. Erstens ist es sehr praktisch und klar, den Code an einer Tabelle auszurichten. Zweitens überladen Sie Ausdrücke nicht mit Klammern. Dieser Code kann beispielsweise folgendermaßen umgeschrieben werden:

 const bool isLetterOrDigit = (ch >= 0x0FF10 && ch <= 0x0FF19) // 0..9 || (ch >= 0x0FF21 && ch <= 0x0FF3A) // A..Z || (ch >= 0x0FF41 && ch <= 0x0FF5A); // a..z if (!isLetterOrDigit) 

Dann wird zum einen die Anzahl der Klammern viel kleiner, und zum anderen steigt die Wahrscheinlichkeit, einen von den Augen begangenen Fehler zu „fangen“.

Und jetzt - Kirsche: Wir bewegen uns an die erste Stelle!

Der erste Platz


Quelle: System in Shock: Interessante Fehler in den Quellcodes des legendären System Shock

Der Finalist unseres heutigen Top ist also ein Fehler des legendären System Shock! Dieses Spiel, das 1994 veröffentlicht wurde, wurde zum Vorläufer und Inspirator von legendären Spielen wie Dead Space, BioShock und Deus Ex.

Aber zuerst muss ich etwas zugeben. Was ich Ihnen jetzt zeigen werde, enthält keinen Fehler. Im Großen und Ganzen ist es nicht einmal ein Code-Snippet, aber ich konnte einfach nicht widerstehen, dies nicht mit Ihnen zu teilen!

Tatsache ist, dass meine Kollegin Victoria bei der Analyse des Quellcodes des Spiels viele interessante Kommentare gefunden hat. Hier und da gab es plötzlich scherzhafte und ironische Bemerkungen und sogar Verse:

 // I'll give you fish, I'll give you candy, // I'll give you, everything I have in my hand // that kid from the wrong side came over my house again, // decapitated all my dolls // and if you bore me, you lose your soul to me // - "Gepetto", Belly, _Star_ // And here, ladies and gentlemen, // is a celebration of C and C++ and their untamed passion... // ================== TerrainData terrain_info; // Now the actual stuff... // ======================= // this is all outrageously horrible, as we dont know what // we really need to deal with here // And if you thought the hack for papers was bad, // wait until you see the one for datas... - X // Returns whether or not in the humble opinion of the // sound system, the sample should be politely obliterated // out of existence // it's a wonderful world, with a lot of strange men // who are standing around, and they all wearing towels 

Für unsere russischsprachigen Leser habe ich eine ungefähre kostenlose Übersetzung angefertigt:
 //    ,    , //    ,       //      //      //     //     ,      // - "Gepetto", Belly, _Star_ //  ,   , //    C  C++     // ================== TerrainData terrain_info; //    ... // ======================= //    ,     , //         //    ,          //      ,      ... - X //       , //         //   ,     //   ,     

Diese Kommentare wurden von den Entwicklern des Spiels in den frühen neunziger Jahren hinterlassen ... Übrigens schrieb Doug Church - der Chefdesigner von System Shock - auch Code. Wer weiß, vielleicht wurde einer dieser Kommentare von ihm persönlich geschrieben? Ich hoffe das über Männer in Handtüchern - das ist nicht seine Arbeit :)

Fazit


Abschließend möchte ich meinen Kollegen dafür danken, dass sie nach neuen Fehlern gesucht und Artikel darüber geschrieben haben. Danke Jungs!Ohne Sie wäre dieser Artikel nicht so interessant geworden.

Ich möchte auch ein wenig über unsere Erfolge sprechen, denn seit einem ganzen Jahr beschäftigen wir uns nicht nur mit der Suche nach Fehlern. Wir haben auch den Analysator entwickelt und verbessert, wodurch er signifikante Änderungen erfahren hat.

Beispielsweise haben wir Unterstützung für mehrere neue Compiler hinzugefügt und die Liste der Diagnoseregeln erweitert. Wir haben auch erste Unterstützung für die Standards MISRA C und MISRA C ++ bereitgestellt . Die wichtigste und zeitaufwändigste Neuerung war die Unterstützung einer neuen Sprache. Ja, jetzt können wir Java- Code analysieren ! Und wir haben das Symbol aktualisiert :)

Ich möchte auch unseren Lesern danken. Vielen Dank, dass Sie unsere Artikel gelesen und uns geschrieben haben! Ihr Feedback ist sehr angenehm und wichtig für uns.

Damit sind unsere Top 10 C ++ - Fehler für das Jahr 2018 zu Ende gegangen. Welche Orte haben Ihnen am besten gefallen und warum? Sind Sie 2018 auf interessante Beispiele gestoßen? Erzähl uns davon in den Kommentaren!

Bis zum nächsten Mal!



Wenn Sie diesen Artikel einem englischsprachigen Publikum zugänglich machen möchten, verwenden Sie bitte den Link zur Übersetzung: George Gribkov. Top 10 Fehler von C ++ - Projekten im Jahr 2018 gefunden

Source: https://habr.com/ru/post/de444570/


All Articles