Das Studium des Taschenrechnercodes geht weiter! In dieser Überprüfung wird das SpeedCrunch-Projekt überprüft - das zweitbeliebteste unter kostenlosen Taschenrechnern.
Einführung
SpeedCrunch ist ein hochpräziser, wissenschaftlicher Tastaturrechner mit schneller Benutzeroberfläche. Dies ist kostenlose Open Source-Software, die unter Windows, Linux und macOS verfügbar ist.
Der Quellcode wird auf
BitBucket gehostet. Die Montagedokumentation, die meiner Meinung nach ausführlicher geschrieben werden sollte, hat mir nicht wirklich gefallen. Die Anforderungen spezifizieren "Qt 5.2 oder höher", obwohl mehrere spezifische Pakete benötigt wurden, die nicht einfach aus dem CMake-Protokoll zu lernen waren. Übrigens empfiehlt es sich jetzt, eine Docker-Datei auf ein Projekt anzuwenden, um die gewünschte Entwicklerumgebung schnell zu konfigurieren.
Zum Vergleich mit anderen Taschenrechnern bringe ich die Ausgabe des Cloc-Dienstprogramms:
Bewertungen von Fehlern in anderen Projekten:
PVS-Studio wurde als statisches Analysewerkzeug verwendet. Dies ist eine Reihe von Lösungen für die Codequalitätskontrolle, die Suche nach Fehlern und potenziellen Schwachstellen. Unterstützte Sprachen sind: C, C ++, C # und Java. Der Analysator kann unter Windows, Linux und MacOS gestartet werden.
Seltsame Logik in einer Schleife
V560 Ein Teil des bedingten Ausdrucks ist immer wahr:! RuleFound. evaluator.cpp 1410
void Evaluator::compile(const Tokens& tokens) { .... while (!syntaxStack.hasError()) { bool ruleFound = false;
Beachten Sie die Variable
ruleFound . Bei jeder Iteration wird der Wert auf false gesetzt. Wenn Sie sich jedoch den Hauptteil des gesamten Zyklus ansehen, wird diese Variable unter bestimmten Bedingungen auf true gesetzt, sie wird jedoch bei der neuen Iteration des Zyklus nicht berücksichtigt. Höchstwahrscheinlich musste die Variable
ruleFound vor der Schleife deklariert werden.
Verdächtige Vergleiche
V560 Ein Teil des bedingten Ausdrucks ist immer wahr: m_scrollDirection! = 0. resultdisplay.cpp 242
void ResultDisplay::fullContentScrollEvent() { QScrollBar* bar = verticalScrollBar(); int value = bar->value(); bool shouldStop = (m_scrollDirection == -1 && value <= 0) || (m_scrollDirection == 1 && value >= bar->maximum()); if (shouldStop && m_scrollDirection != 0) {
Wenn die Variable
shouldStop true ist , hat die Variable
m_scrollDirection einen von zwei Werten: -1 oder 1. Daher ist in der folgenden bedingten Anweisung der Wert der Variablen
m_scrollDirection definitiv nicht Null, worüber der Analysator warnt.
V668 Es macht keinen Sinn, den Zeiger 'item' gegen null zu testen, da der Speicher mit dem Operator 'new' zugewiesen wurde. Die Ausnahme wird bei einem Speicherzuordnungsfehler generiert. editor.cpp 998
void EditorCompletion::showCompletion(const QStringList& choices) { .... for (int i = 0; i < choices.count(); ++i) { QStringList pair = choices.at(i).split(':'); QTreeWidgetItem* item = new QTreeWidgetItem(m_popup, pair); if (item && m_editor->layoutDirection() == Qt::RightToLeft) item->setTextAlignment(0, Qt::AlignRight); .... } .... }
Der Speicher für ein Objekt vom Typ
QTreeWidgetItem wird mit dem neuen Operator zugewiesen. Dies bedeutet, dass eine Ausnahme
std :: bad_alloc () ausgelöst wird, wenn keine dynamische Speicherzuordnung möglich ist. Daher ist das Überprüfen des
Elementzeigers überflüssig und kann gelöscht werden.
Mögliche NULL-Dereferenzierung
V595 Der Zeiger 'ioparams' wurde verwendet, bevor er gegen nullptr verifiziert wurde. Überprüfen Sie die Zeilen: 969, 983. floatio.c 969
int cattokens(....) { .... if (printexp) { if (expbase < 2) expbase = ioparams->expbase;
Der
ioparams- Zeiger
wird dereferenziert, bevor er auf Gültigkeit überprüft wird. Höchstwahrscheinlich hat sich ein potenzieller Fehler in den Code eingeschlichen. Da die Dereferenzierung unter verschiedenen Bedingungen erfolgt, kann sich das Problem selten, aber genau manifestieren.
Division durch Null
V609 Durch Null teilen. Nennerbereich [0..4]. floatconvert.c 266
static int lgbase( signed char base) { switch(base) { case 2: return 1; case 8: return 3; case 16: return 4; } return 0;
Mit der Funktion
lgbase kann ein Nullwert zurückgegeben werden, durch den dann die Division durchgeführt wird. Möglicherweise kann alles andere als die Werte 2, 8 und 16 an die Funktion übergeben werden.
Undefiniertes Verhalten
V610 Undefiniertes Verhalten. Überprüfen Sie den Schichtführer '<<'. Der linke Operand '(~ 0)' ist negativ. floatlogic.c 64
static char _signextend( t_longint* longint) { unsigned mask; signed char sign; sign = _signof(longint); mask = (~0) << SIGNBIT;
Das Ergebnis der Umkehrung von Null wird in den vorzeichenbehafteten Typ
int gesetzt , sodass das Ergebnis eine negative Zahl ist, für die dann eine Verschiebung durchgeführt wird. Das Verschieben einer negativen Zahl nach links ist ein undefiniertes Verhalten.
Die ganze Liste gefährlicher Orte:
- V610 Undefiniertes Verhalten. Überprüfen Sie den Schichtführer '<<'. Der linke Operand '(- 1)' ist negativ. floatnum.c 289
- V610 Undefiniertes Verhalten. Überprüfen Sie den Schichtführer '<<'. Der linke Operand '(- 1)' ist negativ. floatnum.c 325
- V610 Undefiniertes Verhalten. Überprüfen Sie den Schichtführer '<<'. Der linke Operand '(- 1)' ist negativ. floatnum.c 344
- V610 Undefiniertes Verhalten. Überprüfen Sie den Schichtführer '<<'. Der linke Operand '(- 1)' ist negativ. floatnum.c 351
Nicht geschlossene HTML-Tags
V735 Möglicherweise ein falsches HTML. Das schließende Tag "</ body>" wurde gefunden, während das Tag "</ div>" erwartet wurde. book.cpp 127
static QString makeAlgebraLogBaseConversionPage() { return BEGIN INDEX_LINK TITLE(Book::tr("Logarithmic Base Conversion")) FORMULA(y = log(x) / log(a), log<sub>a</sub>x = log(x) / log(a)) END; }
Wie so oft bei C / C ++ - Code ist aus der Quelle nichts ersichtlich. Wenden wir uns daher dem vorverarbeiteten Code für dieses Fragment zu:

Der Analysator hat ein nicht geschlossenes Div-Tag erkannt. Diese Datei enthält viele Fragmente von HTML-Code, die jetzt zusätzlich von den Entwicklern überprüft werden sollten.
Hier sind einige weitere verdächtige Orte, die mit PVS-Studio gefunden wurden:
- V735 Möglicherweise ein falsches HTML. Das schließende Tag "</ td>" wurde gefunden, während das Tag "</ sub>" erwartet wurde. book.cpp 344
- V735 Möglicherweise ein falsches HTML. Das schließende Tag "</ td>" wurde gefunden, während das Tag "</ sub>" erwartet wurde. book.cpp 347
Zuweisungsoperator
V794 Der Zuweisungsoperator sollte vor dem Fall 'this == & other' geschützt werden. Quantity.cpp 373
Quantity& Quantity::operator=(const Quantity& other) { m_numericValue = other.m_numericValue; m_dimension = other.m_dimension; m_format = other.m_format; stripUnits(); if(other.hasUnit()) { m_unit = new CNumber(*other.m_unit); m_unitName = other.m_unitName; } cleanDimension(); return *this; }
Es wird empfohlen, die Situation zu berücksichtigen, in der das Objekt sich selbst zugewiesen wird, indem die Zeiger verglichen werden.
Mit anderen Worten, die folgenden zwei Codezeilen sollten am Anfang des Funktionskörpers hinzugefügt werden:
if (this == &other) return *this;
Erinnerung
V601 Der Wert 'false' wird implizit in den Integer-Typ umgewandelt. cmath.cpp 318
int CNumber::compare(const CNumber& other) const { if (isReal() && other.isReal()) return real.compare(other.real); else return false;
In den Kommentaren zu unseren Artikeln wird manchmal darauf hingewiesen, dass einige Warnungen auf einen unvollständigen Code ausgegeben werden. Ja, es passiert, aber wenn es wirklich so ist, wird es direkt darüber geschrieben.
Fazit
Bereits verfügbare Testberichte zu drei Taschenrechnern: Windows Calculator, Qalculate! und SpeedCrunch. Wir sind bereit, den Code gängiger Taschenrechner weiter zu erforschen. Sie können Projekte zur Überprüfung anbieten, da die Bewertungen der Software nicht immer das tatsächliche Bild widerspiegeln.
Überprüfen Sie Ihren "Rechner", indem Sie
PVS-Studio herunterladen und Ihr Projekt anprobieren :-)

Wenn Sie diesen Artikel einem englischsprachigen Publikum zugänglich machen möchten, verwenden Sie bitte den Link zur Übersetzung: Svyatoslav Razmyslov.
Auf den Spuren von Taschenrechnern: SpeedCrunch