Warten auf die Linux-Version: Überprüfen des Inkscape-Image-Editor-Codes

    Dieser Artikel befasst sich mit dem Testen eines weiteren bekannten Open Source-Projekts - dem Inkscape 0.92-Vektorgrafiken-Editor. Das Projekt wird seit über 12 Jahren entwickelt und bietet viele Möglichkeiten, mit verschiedenen Formaten von Vektorillustrationen zu arbeiten. In dieser Zeit wuchs die Codebasis auf 600.000 Zeilen und es wurde Zeit, sie mit dem statischen Analysegerät PVS-Studio zu testen.


    Einleitung


    Inkscape ist ein plattformübergreifender kostenloser Vektorgrafik-Editor. Es wird von Amateuren und Profis auf der ganzen Welt häufig zum Erstellen von Illustrationen, Symbolen, Logos, Diagrammen, Karten und Webgrafiken verwendet. Inkscape hat sich zu einem der beliebtesten Redakteure auf seinem Gebiet entwickelt. Das Projekt wurde 2003 als Fork des Sodipodi-Projekts ins Leben gerufen und befindet sich noch in der Entwicklung. Weitere Informationen zu Inkscape finden Sie auf der offiziellen Website .

    Für die Überprüfung wurde die neueste Version von Inkscape verwendet - 0.92, deren Code im Repository von GitHub und dem statischen Analysator PVS-Studio 6.07 verfügbar ist , die über den Link heruntergeladen werden können. Zum Zeitpunkt des Schreibens steht jedoch nur PVS-Studio für Windows zum Download zur Verfügung. Aber die Situation wird sich bald ändern. Und Sie können sich bereits für Freiwillige anmelden, um die Beta-Version von PVS-Studio für Linux zu testen. Details finden Sie im Artikel: " PVS-Studio erklärt die Liebe zu Linux ".



    Aber zurück zu den Fehlern. Ich möchte darauf hinweisen, dass der Artikel die interessantesten Analyzer-Meldungen ausgewählt und beschrieben hat. Zur genaueren Überprüfung können die Projektautoren einen temporären Schlüssel für PVS-Studio und einen Bericht von uns erhalten. Da es noch kein öffentliches PVS-Studio gibt, können sie das unter Windows ausgeführte PVS-Studio Standalone-Tool verwenden, um den Bericht anzuzeigen. Ja, das ist nicht bequem. Aber ich bitte alle um etwas Geduld, es ist nicht lange her, bis PVS-Studio für Linux veröffentlicht wird.

    Validierungsergebnisse


    Überprüfung eines Zeigers auf Null nach Neu


    PVS-Studio Warnung: V668 Es hat keinen Sinn, den Zeiger 'outputBuf' gegen null zu testen, da der Speicher mit dem Operator 'new' zugewiesen wurde. Die Ausnahme wird im Fall eines Speicherzuordnungsfehlers generiert. gzipstream.cpp 180
    bool GzipInputStream::load()
    {
        ....
        outputBuf = new unsigned char [OUT_SIZE];
        if ( !outputBuf ) {  // <=
            delete[] srcBuf;
            srcBuf = NULL;
            return false;
        }
        ....
    }

    Gemäß dem modernen C ++ - Standard löst der neue Operator eine Ausnahme std :: bad_alloc () aus , wenn kein Speicher zugewiesen werden kann , und gibt kein nullptr zurück . Wenn das System keinen Speicher zuweist, wird eine Ausnahme ausgelöst und die Ausführung der Funktion wird abgebrochen. Daher wird das Programm nach der Bedingung niemals in den Block eintreten.

    In diesem Fall kann dies zu einem Speicherverlust führen. Die naheliegendste Lösung ist einen Block von verwenden try {....} catch - Anweisung (const std :: bad_alloc &) {....} , aber viel besser, statt explizit freie Speicher intelligente Zeiger zu verwenden ( Reise intelligente Zeiger ).

    Ähnliche Zeigerprüfungen:

    • V668 Es hat keinen Sinn, den Zeiger 'destbuf' gegen null zu testen, da der Speicher mit dem Operator 'new' zugewiesen wurde. Die Ausnahme wird im Fall eines Speicherzuordnungsfehlers generiert. gzipstream.cpp 397
    • V668 Es hat keinen Sinn, den Zeiger 'srcBuf' gegen null zu testen, da der Speicher mit dem Operator 'new' zugewiesen wurde. Die Ausnahme wird im Fall eines Speicherzuordnungsfehlers generiert. gzipstream.cpp 175
    • V668 Es hat keinen Sinn, den Zeiger 'oldcurve' gegen null zu testen, da der Speicher mit dem Operator 'new' zugewiesen wurde. Die Ausnahme wird im Fall eines Speicherzuordnungsfehlers generiert. sp-lpe-item.cpp 719


    Vergleicht man dies mit Null


    PVS-Studio Warnung : V704 '! Dieser' Ausdruck in bedingten Anweisungen sollte vermieden werden - dieser Ausdruck ist bei neueren Compilern immer falsch, da 'dieser' Zeiger niemals NULL sein kann. sp-lpe-item.cpp 213

    bool SPLPEItem::performPathEffect(....) {
        if (!this) {
            return false;
        }
        ....
    }

    Gemäß dem modernen C ++ - Standard kann dieser Zeiger niemals null sein. Die Verwendung dieses Vergleichs mit Null kann häufig zu unerwarteten Fehlern führen. Weitere Informationen hierzu finden Sie in der Beschreibung der V704- Diagnose .

    Noch eine Überprüfung der Gleichheit dieses Wertes mit dem Wert nullptr :

    • V704-Ausdruck "this" in bedingten Anweisungen sollte vermieden werden - dieser Ausdruck gilt immer für neuere Compiler, da dieser Zeiger niemals NULL sein kann. sp-paint-server.cpp 42


    Gefährliche Parameterüberschreibung


    PVS-Studio Warnung: V581 Die bedingten Ausdrücke der nebeneinander liegenden ' wenn' -Operatoren sind identisch. Überprüfen Sie die Zeilen: 1046, 1051. sp-mesh-array.cpp 1051

    void SPMeshNodeArray::create( ...., Geom::OptRect bbox ) // <=
    {
      ....
      if( !bbox ) {
        std::cout << "SPMeshNodeArray::create(): bbox empty" 
                  << std::endl;
        Geom::OptRect bbox = item->geometricBounds();        // <=
      }
      if( !bbox ) {                                          // <=
        std::cout << "ERROR: No bounding box!" 
                  << std::endl;
        return;
      }
      ....
    }

    Nach Ansicht der Autoren in dem Fall, in dem der Parameter bbox ist nullptr , denn es ist ein neues Objekt des Typs erstellen müssen Geom :: OptRect , und wenn Sie ein Objekt nicht erstellen kann, dann wird das Verfahren mit einer Fehlermeldung beendet.

    Der Code funktioniert jedoch überhaupt nicht wie vom Autor erwartet. Wenn der Parameter bbox den Wert nullptr hat , wird im ersten if- Block ein völlig neues bbox- Objekt erstellt , das beim Verlassen dieses Blocks sofort zerstört wird. Infolgedessen stellt sich heraus, dass die zweite Bedingung immer dann erfüllt ist, wenn die erste Bedingung erfüllt ist, also jedes Mal, wenn der Parameter bbox nullptr istwird die Methode mit einer Fehlermeldung beendet.

    Dieser Code sollte so geschrieben werden:

    void SPMeshNodeArray::create( ...., Geom::OptRect bbox )
    {
      ....
      if( !bbox ) {
        std::cout << "SPMeshNodeArray::create(): bbox empty" 
                  << std::endl;
        bbox = item->geometricBounds();
        if( !bbox ) {
          std::cout << "ERROR: No bounding box!" 
                    << std::endl;
          return;
        }
      }
      ....
    }


    Zeile falsch auskommentiert


    PVS-Studio Warnung: V628 Es ist möglich, dass die Zeile nicht ordnungsgemäß auskommentiert wurde, wodurch die Funktionslogik des Programms geändert wurde. FontFactory.cpp 705

    font_instance *font_factory::Face(....)
    {
      ....
      if( features[0] != 0 ) // <=
        // std::cout << "          features: " << std::endl;
      for( unsigned k = 0; features[k] != 0; ++k ) {
      // dump_tag( &features[k], "            feature: ");
      ++(res->openTypeTables[ extract_tag(&features[k])]);
      }
      ....
    }

    Hier hat der Autor vergessen, die Zeile mit der Bedingung, die für das Debuggen verwendet wurde, auszukommentieren. In diesem Fall war es ein Glücksfall und dies führte nicht zu negativen Konsequenzen. Es stellte sich heraus , dass die Bedingung in der , wenn nur die Bedingung der Schleife Duplikat für die erste Iteration, aber es ist sicherlich ein Fehler , und kann zu Problemen in der Zukunft führen.

    "Einmaliger Zyklus"


    PVS-Studio Warnung: V612 Eine bedingungslose Unterbrechung innerhalb einer Schleife. text_reassemble.c 417

    int TR_kern_gap(....)
    { 
      ....
      while(ptsp && tsp){
        ....
        if(!text32){
          ....
          if(!text32)break;
        }
        ....
        if(!ptxt32){
          ....
          if(!ptxt32)break;
        }
        ....
        break; // <=
      }
      ....
      return(kern);
    }

    In jedem Fall endet dieser Zyklus nach dem ersten Durchlauf, da vor der break- Anweisung keine Bedingung vorliegt. Es ist schwer genau zu sagen, was der Autor meinte. Wenn hier kein Fehler vorhanden ist, ist der Code noch besser neu zu schreiben und zu ersetzen , während auf die , wenn .

    Sehr seltsame Methode


    PVS-Studio Warnung: V571 Wiederkehrende Prüfung. Die Bedingung 'back == false' wurde bereits in Zeile 388 überprüft. Path.cpp 389

    void
    Path::SetBackData (bool nVal)
    {
      if (back == false) {
        if (nVal == true && back == false) {
          back = true;
          ResetPoints();
        } else if (nVal == false && back == true) {
          back = false;
          ResetPoints();
        }
      } else {
        if (nVal == true && back == false) {
          back = true;
          ResetPoints();
        } else if (nVal == false && back == true) {
          back = false;
          ResetPoints();
        }
      }
    }

    Es ist schwer zu sagen, warum diese Methode so seltsam geschrieben wurde. Die Blöcke if und else sind identisch, es werden viele zusätzliche Prüfungen durchgeführt. Auch wenn hier kein logischer Fehler vorliegt, sollte diese Methode unbedingt wie folgt umgeschrieben werden:

    void
    Path::SetBackData (bool nVal)
    {
      back = nVal;
      ResetPoints();
    }


    Komma verloren


    PVS-Studio Warnung: V737 Es ist möglich, dass am Ende der Zeichenfolge das Komma ',' fehlt. drawing-text.cpp 272
    void DrawingText::decorateStyle(....)
    {
      ....
      int dashes[16]={
         8,  7,   6,   5,
         4,  3,   2,   1,
        -8, -7,  -6,  -5  // <=
        -4, -3,  -2,  -1
      };
      ....
    }

    Ein Komma wurde weggelassen, was dazu führt, dass das Bindestrich- Array mit völlig anderen Werten als vom Autor erwartet initialisiert wird.

    Erwartet:

    { 8,  7,  6,  5,
      4,  3,  2,  1,
     -8, -7, -6, -5,
     -4, -3, -2, -1 } 

    Tatsächlich wird das Array folgendermaßen gefüllt:

    { 8,  7,  6,  5, 
      4,  3,  2,  1,
     -8, -7, -6, -9,
     -3, -2, -1,  0 }

    Anstelle des 12. Elements des Arrays wird die Zahl -5 - 4 == -9 geschrieben . Und das letzte Element (für das es nicht genügend Elemente in der Array-Initialisierungsliste gab) wird gemäß dem C ++ - Standard auf Null initialisiert.

    Falsche Länge in strncmp


    PVS-Studio Warnung: V666 Betrachten Sie das dritte Argument der Funktion 'strncmp'. Möglicherweise entspricht der Wert nicht der Länge eines Strings, der mit dem zweiten Argument übergeben wurde. blend.cpp 85

    static Inkscape::Filters::FilterBlendMode
     sp_feBlend_readmode(....) {
      ....
      switch (value[0]) {
        case 'n':
          if (strncmp(value, "normal", 6) == 0)
            return Inkscape::Filters::BLEND_NORMAL;
          break;
        case 'm':
          ....
        case 's':
          if (strncmp(value, "screen", 6) == 0)
              return Inkscape::Filters::BLEND_SCREEN;
          if (strncmp(value, "saturation", 6) == 0) // <=
              return Inkscape::Filters::BLEND_SATURATION;
          break;
        case 'd':
          ....
        case 'o':
          if (strncmp(value, "overlay", 7) == 0)
              return Inkscape::Filters::BLEND_OVERLAY;
          break;
        case 'c':
          ....
        case 'h':
          if (strncmp(value, "hard-light", 7) == 0) // <=
              return Inkscape::Filters::BLEND_HARDLIGHT;
          ....
          break;
        ....
      }
    }

    Die falsche Zeichenfolgenlänge "Sättigung" und "Hart" wird an die Funktion " strncmp" übergeben , sodass nicht alle Zeichen verglichen werden, sondern nur die ersten 6 bzw. 7 Zeichen. Höchstwahrscheinlich die sogenannte Kopieren-Einfügen-Programmierung . Dieser Fehler führt zu Fehlalarmen, wenn dem Schaltergehäuse neue Elemente hinzugefügt werden . Es lohnt sich, den Code zu korrigieren:
    if (strncmp(value, "saturation", 10) == 0)
    ....
    if (strncmp(value, "hard-light", 10) == 0)


    Potentielle Division durch Null


    Warnung PVS-Studio: V609 Durch Null teilen. Nennerbereich [0..999]. lpe-fillet-chamfer.cpp 607

    Geom::PathVector
    LPEFilletChamfer::doEffect_path(....)
    {
      ....
      if(....){
        ....
      } else if (type >= 3000 && type < 4000) {
          unsigned int chamferSubs = type-3000;
          ....
          double chamfer_stepsTime = 1.0/chamferSubs;
          ....
      }
      ...
    }

    In dem Fall , in dem der Variable Typ gleich 3000 , wird der Wert von chamferSubs 0. Somit wird der Wert chamfer_stepsTime gleich 1,0 / 0 == die inf , aber das ist eindeutig nicht das, was der Autor erwartet. Um dies zu vermeiden, empfiehlt es sich, die Bedingung im if- Block zu ändern :

    ...
    else if (type > 3000 && type < 4000)
    ...

    Oder Sie können die Situation separat behandeln, wenn chamferSubs == 0 ist .

    Eine ähnliche Situation:

    • V609 Durch Null teilen. Nennerbereich [0..999]. lpe-fillet-chamfer.cpp 623


    Vermissen Sie noch etwas?


    PVS-Studio Warnung: V646 Überlegen Sie, ob Sie die Logik der Anwendung überprüfen möchten . Möglicherweise fehlt das Schlüsselwort "else". sp-item.cpp 204

    void SPItem::resetEvaluated() 
    {
      if ( StatusCalculated == _evaluated_status ) {
        ....
      } if ( StatusSet == _evaluated_status ) { // <=
          ....
      }
    }

    Gemessen an der Formatierung des Codes (die if-Anweisung befindet sich in derselben Zeile wie die schließende Klammer des vorherigen if ) und der Arbeitslogik fehlte hier das Schlüsselwort else :

    ....
    if ( StatusCalculated == _evaluated_status ) {
        ....
      } else if ( StatusSet == _evaluated_status ) {
          ....
      }
    }
    ....


    Nullzeigeroperation


    PVS-Studio Warnung: V595 Der Zeiger 'priv' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Überprüfen Sie die Zeilen: 154, 160. document.cpp 154

    SPDocument::~SPDocument() 
    {
      priv->destroySignal.emit();                      // <=
      ....
      if (oldSignalsConnected) {
        priv->selChangeConnection.disconnect();        // <=
        priv->desktopActivatedConnection.disconnect(); // <=
      } else {
        ....
      }
      if (priv) {                                      // <=
        ....
      }
      ....
    }

    Der untere Block , wenn es eine Überprüfung priv auf NULL , da der Autor gibt die Gleichheit dieses Zeigers mit Null zu, der oben genannte Zeiger wird jedoch bereits ohne Prüfung verwendet. Um diesen Fehler zu beheben, sollten Sie den Wert des Zeigers überprüfen, bevor Sie ihn verwenden.

    Ähnliche Warnungen:

    • V595 Der Zeiger 'parts' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Zeilen prüfen: 624, 641. sp-offset.cpp 624
    • V595 Der Zeiger '_effects_list' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Zeilen überprüfen: 103, 113. effect.cpp 103
    • V595 Der 'num'-Zeiger wurde verwendet, bevor er gegen nullptr verifiziert wurde. Zeilen überprüfen: 1312, 1315. cr-tknzr.c 1312
    • V595 Der 'Selector'-Zeiger wurde verwendet, bevor er gegen nullptr verifiziert wurde. Zeilen prüfen: 3463, 3481. cr-parser.c 3463
    • V595 Der Zeiger 'a_this' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Zeilen prüfen: 1552, 1562. cr-sel-eng.c 1552
    • V595 Der Zeiger 'FillData' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Zeilen überprüfen: 5898, 5901. upmf.c 5898
    • V595 Der Zeiger 'event_context' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Überprüfen Sie die Zeilen: 1014, 1023. tool-base.cpp 1014
    • V595 Der Zeiger 'event_context' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Zeilen überprüfen: 959, 970. tool-base.cpp 959
    • V595 Der Zeiger 'this-> repr' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Überprüfen Sie die Zeilen: 662, 665. eraser-tool.cpp 662
    • V595 Der Zeiger 'this-> repr' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Überprüfen Sie die Zeilen: 662, 665. eraser-tool.cpp 662
    • V595 Der Zeiger 'modified_connection' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Check lines: 1114, 1122. gradient-vector.cpp 1114
    • V595 Der Zeiger 'c' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Überprüfen Sie die Zeilen: 762, 770. freehand-base.cpp 762
    • V595 Der Zeiger 'release_connection' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Zeilen prüfen: 505, 511. Farbverlauf-Symbolleiste.cpp 505
    • V595 Der Zeiger 'modified_connection' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Überprüfen Sie die Zeilen: 506, 514. gradient-toolbar.cpp 506


    Fehlendes Semikolon


    PVS-Studio Warnung : V504 Es ist sehr wahrscheinlich, dass das Semikolon ';' fehlt nach dem Schlüsselwort "return". svg-fonts-dialog.cpp 167

    void GlyphComboBox::update(SPFont* spfont)
    {
      if (!spfont) return // <=
    //TODO: figure out why do we need to append("")
    // before clearing items properly...
    //Gtk is refusing to clear the combobox 
    //when I comment out this line
      this->append(""); 
      this->remove_all();
    }



    Nach der Rückkehr fehlt ein Semikolon (";"), was die Ursache des in den Kommentaren des Autors beschriebenen Problems ist. Denn wenn Sie eine Zeile auskommentieren:

     this->append(""); 

    dann bekommen wir einen Entwurf des Formulars:

    if (!spfont) return this->remove_all();

    Dementsprechend wird das Kombinationsfeld nur gelöscht, wenn spfont == NULL ist .

    Unbenutzter Parameter


    PVS-Studio Warnung: Der V763- Parameter 'new_value' wird vor der Verwendung immer im Funktionskörper neu geschrieben. sp-xmlview-tree.cpp 259

    void element_attr_changed(.... const gchar * new_value, ....)
    {
      NodeData *data = static_cast(ptr);
      gchar *label;
      if (data->tree->blocked) return;
      if (0 != strcmp (key, "id") &&
          0 != strcmp (key, "inkscape:label"))
            return;
      new_value = repr->attribute("id"); // <=
      ....
    }

    In dieser Funktion wird der Wert des Parameters new_value immer geändert, bevor er verwendet wird. Es kann sinnvoll sein, new_value aus der Parameterliste zu entfernen , wie Derzeit ist das Vorhandensein dieses Parameters absolut nicht gerechtfertigt.

    Eine ähnliche Situation:
    • V763 Der Parameter 'Widget' wird vor der Verwendung immer im Funktionskörper neu geschrieben. ruler.cpp 923


    Zeiger auf ein nicht vorhandenes Array


    PVS-Studio Warnung: V507 Der Zeiger auf das lokale Array 'n' wird außerhalb des Bereichs dieses Arrays gespeichert. Ein solcher Zeiger wird ungültig. inkscape.cpp 582

    void
    Application::crash_handler (int /*signum*/)
    {
      ....
      if (doc->isModifiedSinceSave()) {
        const gchar *docname;
      ....
      if (docname) {
        ....
        if (*d=='.' && d>docname && dots==2) {
          char n[64];
          size_t len = MIN (d - docname, 63);
          memcpy (n, docname, len);
          n[len] = '\0';
          docname = n;
        }
      }
      if (!docname || !*docname) docname = "emergency";
      ....
    }

    Array n hat eine Lebensdauer, die kürzer ist als die Lebensdauer des Dokumentnamenzeigers . Dies führt zu einem ungültigen Dokumentnamenzeiger . Eine Lösung für das Problem wäre, ein Array n neben dem Zeiger docname zu definieren :

    ....
    if (doc->isModifiedSinceSave()) {
      const gchar *docname;
      char n[64];
    ....

    Ähnliche Hinweise:
    • V507 Der Zeiger auf das lokale Array 'in_buffer' wird außerhalb des Bereichs dieses Arrays gespeichert. Ein solcher Zeiger wird ungültig. inkjar.cpp 371
    • V507 Der Zeiger auf das lokale Array 'out_buffer' wird außerhalb des Bereichs dieses Arrays gespeichert. Ein solcher Zeiger wird ungültig. inkjar.cpp 375


    Ungültiger Objektname in Bedingung


    PVS-Studio- Warnung : V517 Die Verwendung des Musters 'if (A) {...} else if (A) {...}' wurde erkannt. Es ist wahrscheinlich, dass ein logischer Fehler vorliegt. Überprüfen Sie die Zeilen: 640, 643. font-options.cpp 640

    void
    FontVariants::fill_css( SPCSSAttr *css ) 
    {
      ....
      if( _caps_normal.get_active() ) {
        css_string = "normal";
        caps_new = SP_CSS_FONT_VARIANT_CAPS_NORMAL;
      } else if( _caps_small.get_active() ) {
        ....
      } else if( _caps_all_small.get_active() ) {
        ....
      } else if( _caps_all_petite.get_active() ) { // <=
        css_string = "petite";                     // <=
        caps_new = SP_CSS_FONT_VARIANT_CAPS_PETITE;
      } else if( _caps_all_petite.get_active() ) { // <=
        css_string = "all-petite";                 // <=
        caps_new = SP_CSS_FONT_VARIANT_CAPS_ALL_PETITE;
      } 
      ....
    }

    In der Bedingung vor _caps_all_petite.get_active () sollte der Name des Objekts _caps_petite sein , nicht _caps_all_petite . Der Fehler trat höchstwahrscheinlich beim Kopieren und Einfügen auf.

    Fehlerhafte Verwendung numerischer Konstanten


    Warnung PVS-Studio: V624 Die Konstante 0.707107 wird verwendet. Der resultierende Wert könnte ungenau sein. Verwenden Sie die Konstante M_SQRT1_2 von. PathOutline.cpp 1198

    void
    Path::OutlineJoin (....)
    {
      ....
      if (fabs(c2) > 0.707107) {
        ....
      }
      ....
    }

    Такая запись не совсем корректна и может привести к уменьшению точности вычислений. Лучше использовать математические константу M_SQRT1_2 (the inverse of the square root of 2), объявленную в файле . Думаю, на практике здесь всё работает хорошо, но захотелось обратить внимание и на такой пример некрасивого кода.

    Аналогичные предупреждения:
    • V624 The constant 1.414213562 is being utilized. The resulting value could be inaccurate. Consider using the M_SQRT2 constant from . verbs.cpp 1848
    • V624 The constant 3.14159 is being utilized. The resulting value could be inaccurate. Consider using the M_PI constant from . odf.cpp 1568
    • V624 The constant 1.414213562 is being utilized. The resulting value could be inaccurate. Consider using the M_SQRT2 constant from . inkscape-preferences.cpp 1334


    Идентичные выражения


    Предупреждение PVS-Studio: There are identical sub-expressions 'Ar.maxExtent() < tol' to the left and to the right of the '&&' operator. path-intersection.cpp 313
    void mono_intersect(....)
    {
       if(depth > 12 || (Ar.maxExtent() < tol && Ar.maxExtent() < tol)) 
       {
         ....
       }
       ....
    }

    Проверка условия Ar.maxExtent() < tol выполняется дважды. Скорее всего это получилось в результате внесения каких-то исправлений в код. Следует исправить выражение или просто убрать дублирующую проверку.

    Аналогичная проверка:
    • V501 There are identical sub-expressions 'Ar.maxExtent() < 0.1' to the left and to the right of the '&&' operator. path-intersection.cpp 364


    Одинаковые действия в блоках if и else


    Предупреждение PVS-Studio: The 'then' statement is equivalent to the 'else' statement. ShapeRaster.cpp 1825

    void Shape::AvanceEdge(....)
    {
      ....
      if ( swrData[no].sens ) { 
        if ( swrData[no].curX < swrData[no].lastX ) {
          line->AddBord(swrData[no].curX,
                        swrData[no].lastX,
                        false);
        } else if ( swrData[no].curX > swrData[no].lastX ) { 
            line->AddBord(swrData[no].lastX,
                          swrData[no].curX,
                          false);
          }
      } else {
        if ( swrData[no].curX < swrData[no].lastX ) {
          line->AddBord(swrData[no].curX,
                        swrData[no].lastX,
                        false);
        } else if ( swrData[no].curX > swrData[no].lastX ) {
            line->AddBord(swrData[no].lastX,
                          swrData[no].curX,
                          false);
        }
      }
    }

    Код в блоках if и else одинаков, поэтому стоит просмотреть это место и либо исправить логику работы, либо удалить дублирующую ветку.

    Аналогичные места:
    • V523 The 'then' statement is equivalent to the 'else' statement. ShapeRaster.cpp 1795
    • V523 The 'then' statement is equivalent to the 'else' statement. PathCutting.cpp 1323
    • V523 The 'then' statement is equivalent to the 'else' statement. ShapeSweep.cpp 2340


    Заключение


    В ходе проверки было выявлено немало ошибок, допущенных по невнимательности. Статический анализатор PVS-Studio может эффективно выявлять такие ошибки и тем самым экономить время и нервы программиста. Главное выполнять анализ кода регулярно, чтобы сразу выявлять опечатки и прочие недоработки. Разовые проверки, такая как эта, хотя хорошо рекламируют PVS-Studio, но малоэффективны. Рассматривайте сообщения от статического анализатора как расширенные предупреждения от компилятора. А с сообщениями компилятора надо работать постоянно, а не разово перед релизом. Надеюсь эта аналогия близка и понятна душе любого программиста, переживающего за качество кода.

    Предлагаю скачать и попробовать PVS-Studio на своем собственном проекте.

    P.S.




    Unsere Firma hat beschlossen, ein bisschen mit Instagram zu experimentieren. Wir wissen nicht, ob daraus etwas wird, aber ich lade alle ein, " pvsstudio " zu folgen .


    Wenn Sie diesen Artikel mit einem englischsprachigen Publikum teilen möchten, verwenden Sie bitte den Link zur Übersetzung: Egor Bredikhin. Warten auf die Linux-Version: Code des Inkscape Graphics Editor überprüfen .
    Haben Sie den Artikel gelesen und eine Frage?
    Oft werden unseren Artikeln die gleichen Fragen gestellt. Wir haben die Antworten hier gesammelt: Antworten auf Fragen von Lesern von Artikeln über PVS-Studio, Version 2015 . Bitte beachten Sie die Liste.

    Jetzt auch beliebt: