Godot: Regelmäßige Verwendung statischer Codeanalysatoren

    PVS-Studio und GodotDas Publikum unserer Leser wächst, deshalb schreiben wir immer wieder Artikel, in denen wir erklären, wie man die Methodik der statischen Codeanalyse richtig einsetzt. Wir halten es für sehr wichtig zu erklären, dass statische Analysewerkzeuge nicht sporadisch, sondern regelmäßig verwendet werden sollten. Wir werden dies erneut mit einem praktischen Beispiel demonstrieren, nachdem wir das Godot-Projekt erneut geprüft haben.

    Verwenden Sie regelmäßig Analysegeräte


    Als ich mich auf eine Konferenz für Spieleentwickler vorbereitete, beschloss ich, neue Beispiele für interessante Fehler zu erhalten, die das PVS-Studio- Tool aufdecken kann . Zu diesem Zweck wurden mehrere Spiel-Engines getestet, darunter Godot. Ich habe keine besonders interessanten Fehler für den Bericht gefunden, aber ich wollte einen Artikel über gewöhnliche Fehler schreiben. Diese Fehler zeigen sehr gut die Relevanz der regelmäßigen Verwendung statischer Codeanalyse-Tools.

    Es sei darauf hingewiesen, dass wir dieses Projekt bereits 2015 geprüft haben und der Autor mit den von uns geschriebenen Fehlern gearbeitet hat. Hier sehen Sie das entsprechende Commit.

    3 Jahre sind vergangen. Das Projekt hat sich geändert. Der PVS-Studio-Analysator hat sich ebenfalls geändert, und es wurden neue Diagnosefunktionen hinzugefügt. Daher ist es nicht verwunderlich, dass es mir leicht und schnell gelungen ist, eine ausreichende Anzahl von Fehlerbeispielen für das Schreiben dieses Artikels aufzuschreiben.

    Ein anderer ist jedoch wichtig. Bei der Entwicklung von Godot oder anderen Projekten werden ständig neue Fehler angezeigt und korrigiert. Nicht erkannte Fehler "begleichen" sich lange im Code, und viele davon können bei der statischen Codeanalyse erkannt werden. Aus diesem Grund besteht manchmal das falsche Gefühl, dass statische Analysatoren in selten verwendeten Codeteilen nur einige uninteressante Fehler finden. Natürlich ist es so, wenn Sie den Analysator falsch verwenden und ihn nur von Zeit zu Zeit ausführen, beispielsweise kurz vor dem Release der Version.

    Ja, wenn Sie Artikel schreiben, überprüfen wir offene Projekte einmalig. Aber wir haben ein anderes Ziel. Wir möchten die Fähigkeiten des Codeanalysators zur Erkennung von Fehlern demonstrieren. Diese Aufgabe hat wenig damit zu tun, die Qualität des Projektcodes insgesamt zu verbessern und die mit Bearbeitungsfehlern verbundenen Kosten zu reduzieren.

    Noch einmal zur Hauptsache. Die Bedeutung der statischen Code-Analyse besteht nicht darin, veraltete Fehler zu finden. Diese alten Fehler sind normalerweise geringfügig, andernfalls würden sie die Benutzer stören und wären bereits gefunden und korrigiert worden. Die Bedeutung der statischen Analyse zur schnellen Beseitigung von Fehlern in neu geschriebenem oder geändertem Code. Dies reduziert die Debugging-Zeit, die Anzahl der Benutzerbeschwerden und letztendlich das Budget des entwickelten Projekts.

    Wir wenden uns nun den Fehlern zu, die die Leser unserer Publikationen so lieben.

    Fehler beim Kopieren und Einfügen


    Mal sehen, was mir beim Studium des PVS-Studio-Berichts aufgefallen ist. Ich beginne mit meiner bevorzugten V501-Diagnose, die in fast jedem Projekt, das wir überprüfen , Fehler findet :).

    Fehler n1

    virtualboolcan_export(....){
      ....
      if (!exists_export_template("uwp_" + platform_infix + "_debug.zip", &err) ||
          !exists_export_template("uwp_" + platform_infix + "_debug.zip", &err)) {
        valid = false;
        r_missing_templates = true;
      }
      ....
    }

    PVS-Studio-Warnung: V501 CWE-570 Es gibt identische Unterausdrücke! Exists_export_template ("uwp_" + platform_infix + "_debug.zip", & err) 'nach links und rechts Betreiber. export.cpp 1135

    Klassischer Fehler beim Kopieren und Einfügen. Der Funktionsaufruf wird kopiert, aber nicht bearbeitet. Der Name der zweiten verarbeiteten Datei muss mit "_release.zip" enden.

    Fehler N2, N3

    static String dump_node_code(SL::Node *p_node, int p_level){
      ....
      if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW ||
          bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW) {
        code += scode; //use directly
      } else {
        code += _mktab(p_level) + scode + ";\n";
      }
      ....
    }

    PVS-Studio-Warnung: V501 CWE-570 Die bnode-> -Anweisungen für identische Unterausdrücke [i] -> type == SL :: Node :: TYPE_CONTROL_FLOW '|| Betreiber. test_shader_lang.cpp 183

    void EditorSpinSlider::_notification(int p_what) {
      if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_OUT ||
          p_what == MainLoop::NOTIFICATION_WM_FOCUS_OUT) {
        if (grabbing_spinner) {
          Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
          grabbing_spinner = false;
          grabbing_spinner_attempt = false;
        }
      }
      ....
    }

    PVS-Studio Warnung: V501 CWE-570 Es gibt identische Unterausdrücke 'p_what == MainLoop :: NOTIFICATION_WM_FOCUS_OUT' || ' Betreiber. editor_spin_slider.cpp 157

    Ich denke, die Fehler sind deutlich sichtbar und bedürfen keiner Erklärung. Genau das gleiche klassische Kopieren und Einfügen wie im ersten Fall.

    Fehler n4

    String SoftBody::get_configuration_warning() const {
      ....
      Transform t = get_transform();
      if ((ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 ||
           ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 ||
           ABS(t.basis.get_axis(0).length() - 1.0) > 0.05)) {
        if (!warning.empty())
      ....
    }

    PVS-Studio Warnung: V501 CWE-570 ||| Betreiber. soft_body.cpp 399

    Hier wurde die erste Zeile zweimal kopiert. Die Anzahl der Koordinatenachsen wurde jedoch nur in der zweiten Zeile geändert. Und sie vergaßen, die dritte Zeile zu bearbeiten. Dies ist nichts anderes als der " Last Line Effect ".

    Hinweis Im Moment habe ich neben dem "Last Line Effect" folgende interessante Beobachtungen gemacht: " Die gefährlichste Funktion in der C / C ++ - Welt ", "Das Böse lebt in Vergleichsfunktionen. „Ich werde die Ankündigung eines neuen Artikels machen, und jetzt , die schreibt, ich plane in naher Zukunft dem Arbeitstitel zu tun“ 0, 1, 2 „sollten Sie interessant und lehrreich erhalten Sie einladen zu einem der Kanäle zu abonnieren , um nicht zu verpassen: ... Twitter , Dienste vk. com , instagram , telegram und old school rss .

    Fehler N5

    void ScrollContainer::_notification(int p_what) {
      ....
      if (h_scroll->is_visible_in_tree() && h_scroll->get_parent() == this)
        size.y -= h_scroll->get_minimum_size().y;
      if (v_scroll->is_visible_in_tree() && v_scroll->get_parent() == this)
        size.x -= h_scroll->get_minimum_size().x;
      ....
    }

    PVS-Studio Warnung: V778 CWE-682 Es wurden zwei Codefragmente gefunden. Möglicherweise handelt es sich um einen Tippfehler, und die Variable 'v_scroll' sollte anstelle von 'h_scroll' verwendet werden. scroll_container.cpp 249

    In Bezug auf dieses Code-Snippet bin ich nicht vollkommen überzeugt, dass hier ein Fehler vorliegt. Ich stimme dem Analysator jedoch zu, dass der zweite Block sehr verdächtig aussieht. Höchstwahrscheinlich wurde der Code mit Copy-Paste geschrieben und im zweiten Textblock wurde vergessen, h_scroll durch v_scroll zu ersetzen .

    Der Code sollte wahrscheinlich so aussehen:

    if (h_scroll->is_visible_in_tree() && h_scroll->get_parent() == this)
      size.y -= h_scroll->get_minimum_size().y;
    if (v_scroll->is_visible_in_tree() && v_scroll->get_parent() == this)
      size.x -= v_scroll->get_minimum_size().x;

    Fehler N6

    Ein weiterer Fall, bei dem ein ausreichend großer Code kopiert und nicht erfolgreich geändert wurde. Die Zeile mit dem Fehler wird von mir mit dem Kommentar "// <=" markiert.

    void ShaderGLES2::bind_uniforms() {
      ....
      const Map<uint32_t, Variant>::Element *E = uniform_defaults.front();
      while (E) {
        int idx = E->key();
        int location = version->uniform_location[idx];
        if (location < 0) {
          E = E->next();
          continue;
        }
        Variant v;
        v = E->value();
        _set_uniform_variant(location, v);
        E = E->next();
      }
      const Map<uint32_t, CameraMatrix>::Element *C = uniform_cameras.front();
      while (C) {
        int idx = E->key();                                  // <=int location = version->uniform_location[idx];
        if (location < 0) {
          C = C->next();
          continue;
        }
        glUniformMatrix4fv(location, 1, GL_FALSE, &(C->get().matrix[0][0]));
        C = C->next();
      }
      uniforms_dirty = false;
    }

    PVS-Studio-Warnung: V522 CWE-476 Es kann zu einer Dereferenzierung des Nullzeigers 'E' kommen. shader_gles2.cpp 102

    Fehler indirekt erkannt. Durch die Analyse des Datenflusses hat PVS-Studio herausgefunden, dass der E- Zeiger zum Zeitpunkt seiner Dereferenzierung Null sein kann.

    Der Fehler liegt in der Tatsache , dass in dem kopierten Code - Schnipsel vergessen hat , an einem Ort zu ersetzen E auf C . Aufgrund dieses Fehlers arbeitet die Funktion auf sehr seltsame Weise und macht unverständliche Dinge.

    Tippfehler


    Fehler N7 Es ist

    für Nicht-C- oder C ++ - Programmierer schwer vorstellbar, dass durch Schreiben des Kommas * anstelle des Sternchens ein Tippfehler gemacht werden kann, und der Code wird kompiliert. Es ist aber so.

    LRESULT OS_Windows::WndProc(....) {
      ....
      BITMAPINFO bmi;
      ZeroMemory(&bmi, sizeof(BITMAPINFO));
      bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
      bmi.bmiHeader.biWidth = dib_size.x;
      bmi.bmiHeader.biHeight = dib_size.y;
      bmi.bmiHeader.biPlanes = 1;
      bmi.bmiHeader.biBitCount = 32;
      bmi.bmiHeader.biCompression = BI_RGB;
      bmi.bmiHeader.biSizeImage = dib_size.x, dib_size.y * 4;
      ....
    }

    PVS-Studio-Warnung: V521 CWE-480 Solche Ausdrücke, die den Operator ',' verwenden, sind gefährlich. Stellen Sie sicher, dass der Ausdruck korrekt ist. os_windows.cpp 776 Der

    Variablen bmi.bmiHeader.biSizeImage wird der Wert der Variablen dib_size.x zugewiesen . Als nächstes wird der Kommaoperator ',' ausgeführt, dessen Priorität niedriger ist als der Operator '='. Das Ergebnis des Ausdrucks dib_size.y * 4 wird überhaupt nicht verwendet.

    Anstelle eines Kommas im Ausdruck sollte der Multiplikationsoperator '*' verwendet werden. Erstens wäre ein solcher Ausdruck sinnvoll. Zweitens gibt es unten eine ähnliche, aber bereits korrekte Version der Initialisierung derselben Variablen:

    bmi.bmiHeader.biSizeImage = dib_size.x * dib_size.y * 4;

    Fehler N8, N9

    void Variant::set(....) {
      ....
      int idx = p_index;
      if (idx < 0)
        idx += 4;
      if (idx >= 0 || idx < 4) {
        Color *v = reinterpret_cast<Color *>(_data._mem);
        (*v)[idx] = p_value;
        valid = true;
      }
      ....
    }

    PVS-Studio-Warnung: V547 CWE-571 Ausdruck 'idx> = 0 || idx <4 'ist immer wahr. variant_op.cpp 2152

    Jeder Index wird als gültig betrachtet. Um den Fehler zu korrigieren, müssen Sie den Operator || ersetzen am && :

    if (idx >= 0 && idx < 4) {

    Dieser logische Fehler war höchstwahrscheinlich auf Unaufmerksamkeit zurückzuführen, daher neige ich dazu, Tippfehler zuzuordnen.

    Genau der gleiche Fehler kann in derselben Datei unten gesehen werden. Der Fehler bei Wiedergabefehlern ist anscheinend Copy-Paste.

    Ein propagierter Fehler: V547 CWE-571 Ausdruck 'idx> = 0 || idx <4 'ist immer wahr. variant_op.cpp 2527

    Fehler N10

    WTF?

    Ein Beispiel für einen Fehler, von dem man ausrufen möchte: WTF?!

    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 Prüfen Sie den 'for'-Operator. Möglicherweise werden Sie gar nicht hingerichtet. animation_blend_space_1d.cpp 113

    Beachten Sie die Bedingung zum Stoppen der Schleife: i> p_at_index . Dies ist immer wahr, da die Variable i mit dem Wert blend_points_used - 1 initialisiert wird . In diesem Fall ergibt sich aus den beiden vorherigen Prüfungen, dass blend_points_used> p_at_index ist .

    Eine Bedingung kann nur dann zu "false" werden, wenn die Vorzeichenvariable i überläuft , was ein unbestimmtes Verhalten ist. Darüber hinaus kommt es nicht zu einem Überlauf, da es viel früher passieren wird, dass die Arraygrenze überschritten wird.

    Vor uns liegt meiner Meinung nach ein schöner Tippfehler, wenn sie anstelle von '<' '' '' schreiben. Ja, ich habe eine perverse Vorstellung von der Schönheit der Fehler :).

    Richtiger Zyklus:

    for (int i = blend_points_used - 1; i < p_at_index; i++) {

    Fehler N11

    Ein weiterer nicht weniger auffälliger Fall von Tippfehlern im Zykluszustand.

    void AnimationNodeStateMachineEditor::_state_machine_pos_draw() {
      ....
      int idx = -1;
      for (int i = 0; node_rects.size(); i++) {
        if (node_rects[i].node_name == playback->get_current_node()) {
          idx = i;
          break;
        }
      }
      ....
    }

    PVS-Studio-Warnung: V693 CWE-835 Prüfen Sie den Bedingungsausdruck der Schleife. Es ist möglich, dass 'i <X.size ()' anstelle von 'X.size ()' verwendet wird. animation_state_machine_editor.cpp 852

    Das Array kann überschritten werden, da der Wert von i unkontrolliert ansteigt. Sicherer Code:

    for (int i = 0; i < node_rects.size(); i++) {

    Fehler n12

    GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(
      const GDScriptParser::DataType &p_datatype) const
    {
      ....
      switch (p_datatype.kind) {
         ....
        case GDScriptParser::DataType::NATIVE: {
          result.kind = GDScriptDataType::NATIVE;
          result.native_type = p_datatype.native_type;
        } break;
        case GDScriptParser::DataType::SCRIPT: {
          result.kind = GDScriptDataType::SCRIPT;
          result.script_type = p_datatype.script_type;
          result.native_type = result.script_type->get_instance_base_type();
        }
        case GDScriptParser::DataType::GDSCRIPT: {
          result.kind = GDScriptDataType::GDSCRIPT;
          result.script_type = p_datatype.script_type;
          result.native_type = result.script_type->get_instance_base_type();
        } break;
      ....
    }

    PVS-Studio Warnung: V796 CWE-484 In der switch-Anweisung fehlt möglicherweise die 'break'-Anweisung. gdscript_compiler.cpp 137

    Versehentlich vergessen, eine break- Anweisung zu schreiben . Wenn der Treffer in einem Fall von GDScriptParser :: DataType :: SCRIPT getroffen wird, werden Variablen daher Werte zugewiesen, als wäre es ein Fall von GDScriptParser :: DataType :: GDSCRIPT .

    Fehler N13 Der

    folgende Fehler kann als Kopieren / Einfügen klassifiziert werden. Ich bin mir jedoch nicht sicher, ob eine solche kurze Zeile kopiert wurde. Wir werden es also als einfachen Tippfehler betrachten.

    void CPUParticles::_particles_process(float p_delta) {
      ....
      if (flags[FLAG_DISABLE_Z]) {
        p.velocity.z = 0.0;
        p.velocity.z = 0.0;
      }
      ....
    }

    PVS-Studio-Warnung: V519 CWE-563 Die Variable 'p.velocity.z' wird zweimal hintereinander mit Werten belegt. Vielleicht ist das ein Fehler. Überprüfen Sie die Zeilen: 664, 665. cpu_particles.cpp 665 Dieselbe

    Variable zweimal zuweisen . Unten sehen Sie den folgenden Code-Ausschnitt:

    if (flags[FLAG_DISABLE_Z]) {
      p.velocity.z = 0.0;
      p.transform.origin.z = 0.0;
    }

    Für den ersten Fall hätte es höchstwahrscheinlich genauso geschrieben sein müssen.

    Fehler N14

    bool AtlasTexture::is_pixel_opaque(int p_x, int p_y) const {
      if (atlas.is_valid()) {
        return atlas->is_pixel_opaque(
          p_x + region.position.x + margin.position.x,
          p_x + region.position.y + margin.position.y
        );
      }
      returntrue;
    }

    PVS-Studio-Warnung: V751 Der Parameter 'p_y' wird nicht innerhalb des Funktionskörpers verwendet. texture.cpp 1085

    Fragment aus der V751- Diagnosebeschreibung :

    Der Analysator hat eine verdächtige Funktion entdeckt, von der einer der Parameter niemals verwendet wird. Sein anderer Parameter wird jedoch mehrmals verwendet, was auf einen Fehler hindeuten kann.

    Wie Sie sehen, ist dies wahr und es ist sehr misstrauisch. Die Variable p_x wird zweimal verwendet und p_y wird nicht verwendet. Am wahrscheinlichsten sollte es geschrieben werden:

    return atlas->is_pixel_opaque(
      p_x + region.position.x + margin.position.x,
      p_y + region.position.y + margin.position.y
    );

    Im Quellcode ist der Funktionsaufruf übrigens in eine Zeile geschrieben. Aus diesem Grund ist der Fehler schwieriger zu bemerken. Wenn der Autor des Codes wie in dem Artikel die eigentlichen Argumente in die Spalte geschrieben hätte, wäre der Fehler sofort ersichtlich. Vergessen Sie nicht, dass das Formatieren von Tabellen sehr nützlich ist und Sie viele Tippfehler vermeiden können. Siehe Kapitel "Ausrichten des Codes desselben Typs an einer Tabelle" im Artikel " Das Hauptproblem beim Programmieren, Refactoring und all dem ".

    Fehler N15

    bool SpriteFramesEditor::can_drop_data_fw(....) const {
      ....
      Vector<String> files = d["files"];
      if (files.size() == 0)
        returnfalse;
      for (int i = 0; i < files.size(); i++) {
        String file = files[0];
        String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
        if (!ClassDB::is_parent_class(ftype, "Texture")) {
          returnfalse;
        }
      }
      ....
    }

    PVS-Studio-Warnung: V767 Verdächtiger Zugriff auf das Element des Dateisystems durch einen konstanten Index innerhalb einer Schleife. sprite_frames_editor_plugin.cpp 602

    In der Schleife wird dieselbe Datei in allen Iterationen der Schleife verarbeitet. Ein Tippfehler hier:

    String file = files[0];

    Es sollte sein:

    String file = files[i];

    Andere Fehler


    Fehler n16

    CSGBrush *CSGBox::_build_brush() {
      ....
      for (int i = 0; i < 6; i++) {
        ....
        if (i < 3)
          face_points[j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
        else
          face_points[3 - j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
        ....
      }
      ....
    }

    Der PVS-Studio Analyzer generiert sofort zwei Antworten auf diesen Code:

    • V547 CWE-570 Der Ausdruck 'i> = 3' ist immer falsch. csg_shape.cpp 939
    • V547 CWE-571 Der Ausdruck 'i> = 3' ist immer wahr. csg_shape.cpp 941

    Und tatsächlich sieht dieser ternäre Operator in beiden Ausdrücken sehr seltsam aus:

    i >= 3 ? -1 : 1

    In einem Fall ist die Bedingung immer wahr und in dem anderen Fall falsch. Es ist schwer zu sagen, wie dieser Code richtig aussehen sollte. Vielleicht ist es einfach überflüssig und Sie können dies schreiben:

    for (int i = 0; i < 6; i++) {
      ....
      if (i < 3)
        face_points[j][(i + k) % 3] = v[k];
      else
        face_points[3 - j][(i + k) % 3] = -v[k];
      ....
    }

    Ich bin möglicherweise falsch und der Code muss auf eine völlig andere Art und Weise korrigiert werden.

    Fehler N17 Es wurden

    fast keine V595-Fehler gefunden, obwohl sie normalerweise in jedem Projekt reichlich vorhanden sind . Anscheinend wurden diese Fehler nach der vorherigen Überprüfung korrigiert, und dann wurden solche Fehler fast nicht angezeigt. Ich habe nur wenige Fehlalarme und einen Fehler gesehen.

    bool CanvasItemEditor::_get_bone_shape(....) {
      ....
      Node2D *from_node = Object::cast_to<Node2D>(
                            ObjectDB::get_instance(bone->key().from));
      ....
      if (!from_node->is_inside_tree())
        returnfalse; //may have been removedif (!from_node)
        returnfalse;
      ....
    }

    PVS-Studio-Warnung: V595 CWE-476 Der 'from_node' Überprüfen Sie die Zeilen: 565, 567. canvas_item_editor_plugin.cpp 565

    Der from_node- Zeiger wird dereferenziert, um die Funktion is_inside_tree aufzurufen , und wird dann nur auf Gleichheit mit nullptr geprüft . Schecks sollten ausgetauscht werden:

    if (!from_node)
      returnfalse;
    if (!from_node->is_inside_tree())
      returnfalse; //may have been removed

    Fehler n18
    enum JoystickList {
      ....
      JOY_AXIS_MAX = 10,
      ....
    };
    staticconstchar *_axes[] = {
      "Left Stick X",
      "Left Stick Y",
      "Right Stick X",
      "Right Stick Y",
      "",
      "",
      "L2",
      "R2"
    };
    int InputDefault::get_joy_axis_index_from_string(String p_axis) {
      for (int i = 0; i < JOY_AXIS_MAX; i++) {
        if (p_axis == _axes[i]) {
          return i;
        }
      }
      ERR_FAIL_V(-1);
    }

    PVS-Studio-Warnung: V557 CWE-125 Array-Überschreitung ist möglich. Der Wert des Index 'i' könnte 9 erreichen. Input_default.cpp 1119

    Das _axes- Array besteht aus acht Elementen. In diesem Fall ist die JOY_AXIS_MAX- Konstante , die die Anzahl der Iterationen der Schleife angibt, 10. Es stellt sich heraus, dass die Schleife über den Rand des Arrays hinausgeht.

    Fehler N19

    Und die letzte ist eine sehr seltsame Funktion, die anscheinend zum Testen gedacht ist. Die Funktion ist lang, deshalb gebe ich sie in Form eines Bildes (zum Vergrößern auf das Bild klicken).

    Sehr seltsame Funktion



    PVS-Studio-Warnung: V779 CWE-561 Nicht erreichbarer Code erkannt. Es ist möglich, dass ein Fehler vorliegt. test_math.cpp 457

    Die Funktion enthält mehrere bedingungslose Rückgabeanweisungen . Im Bild habe ich sie mit roten Ovalen markiert. Es scheint, dass mehrere verschiedene Komponententests für diese Funktion gesammelt wurden, aber vergessen haben, die zusätzlichen NULL- Werte zu entfernen . Daher prüft die Funktion nicht, was überprüft werden soll. Fast der gesamte Körper einer Funktion besteht aus unerreichbarem Code.

    Vielleicht ist das natürlich eine knifflige Idee. Mir scheint aber, dass dies zufällig passiert ist und der Code behoben werden sollte.

    Darauf lasst uns fertig sein. Wenn Sie den Analysebericht genau betrachten, können Sie sicherlich andere Fehler finden. Allerdings sogar mit mehr als genug ausgeschrieben, um einen Artikel zu schreiben. Dann wird es für mich und den Leser langweilig :).

    Fazit


    Der Artikel beschreibt Fehler, die bei einer regelmäßigen Analyse des Codes mit PVS-Studio nicht vorhanden wären. Noch wichtiger ist jedoch, dass man bei regelmäßiger Analyse viele andere Fehler sofort finden und beheben würde. Mein Kollege hat diese Idee ausführlicher in einer Anmerkung beschrieben: „Die Philosophie der statischen Code-Analyse: Wir haben 100 Programmierer, der Analysator hat wenige Fehler gefunden, ist er nutzlos? “. Ich empfehle dringend, 10 Minuten zu lesen, um diesen kurzen, aber sehr wichtigen Artikel zu lesen.

    Vielen Dank für Ihre Aufmerksamkeit. Ich lade alle ein, die statische Analyse von PVS-Studio herunterzuladen und auszuprobieren, um Ihre eigenen Projekte zu überprüfen.



    Wenn Sie diesen Artikel mit einem englischsprachigen Publikum teilen möchten, verwenden Sie bitte den Link zur Übersetzung: Andrey Karpov. Godot: Zur regelmäßigen Verwendung statischer Analysatoren .

    Jetzt auch beliebt: