Integration von PVS-Studio in PlatformIO

Bild 5

In der Entwicklungsumgebung für eingebettete PlatformIO-Systeme wurde kürzlich die Unterstützung für PVS-Studio angezeigt. In diesem Artikel erfahren Sie, wie Sie Ihren Code mit einem statischen Analysegerät am Beispiel eines offenen Projekts testen.

Was ist PlatformIO?


PlatformIO ist ein plattformübergreifendes Programmierwerkzeug für Mikrocontroller. Der Kern von PlatformIO ist ein Befehlszeilentool. Es wird jedoch empfohlen, es als Plug-In für Visual Studio Code zu verwenden. Eine große Anzahl moderner Chips und darauf basierender Motherboards wird unterstützt. Es kann automatisch geeignete Montagesysteme herunterladen und die Site verfügt über eine große Sammlung von Bibliotheken zur Verwaltung von elektronischen Plug-in-Komponenten. Es werden mehrere statische Code-Analysatoren unterstützt, einschließlich PVS-Studio.

Projekt importieren


Nehmen wir zur Demonstration das ArduPod- Hexapod- Steuerungsprogramm auf der Arduino Mega-Platine.


Erstellen Sie ein neues Projekt für ein geeignetes Board und kopieren Sie den Quellcode:

Bild 2

Im Ordner / arduino / AP_Utils / examples / gibt es mehrere Beispiele für Programme zum Konfigurieren und Ausführen des Hexapods. Wir werden servo_test.ino verwenden. Das Programm für Arduino wird in der Regel in Form von Skizzen im INO-Format erstellt, was in diesem Fall nicht ganz geeignet ist. Um daraus eine korrekte CPP-Datei zu erstellen, reicht es normalerweise aus, die Dateinamenerweiterung zu ändern, den Header #include <Arduino.h> am Anfang hinzuzufügen und sicherzustellen, dass Funktionen und globale Variablen deklariert sind, bevor auf sie zugegriffen wird .

Bild 3

Während des Assemblierungsprozesses können Fehler aufgrund des Fehlens der erforderlichen Bibliotheken von Drittanbietern auftreten. PlatformIO hilft Ihnen jedoch dabei, sie in Ihrem Repository zu finden.

In file included from src\servo_test.cpp:20:0:
src/AP_Utils.h:10:37: fatal error: Adafruit_PWMServoDriver.h:
No such file or directory
*******************************************************************************
* Looking for Adafruit_PWMServoDriver.h dependency? Check our library registry!
*
* CLI> platformio lib search "header:Adafruit_PWMServoDriver.h"
* Web> https://platformio.org/lib/search?query=header:Adafruit_PWMServoDriver.h
*
*******************************************************************************
compilation terminated.

Der Link zeigt die entsprechenden Optionen an, und die Installation der Abhängigkeit erfolgt mit einem Befehl im Terminal:

pio lib install "Adafruit PWM Servo Driver Library"

Analysatoren konfigurieren und Test starten


Um die Analysatoren zu konfigurieren, müssen Sie die Plattformplattform.ini wie folgt bearbeiten:

[env:megaatmega2560]
platform = atmelavr
board = megaatmega2560
framework = arduino
check_tool = pvs-studio
check_flags =
  pvs-studio:
    --analysis-mode=4 ; General analysis mode. Set to 32 for MISRA
    --exclude-path=/.pio/libdeps ; Ignore dependency libraries

Der Parameter check_tool gibt an, welche Codeanalysatoren verwendet werden sollen, und ihre Konfiguration erfolgt im Parameter check_flags . Ausführlichere Anweisungen finden Sie in der Dokumentation auf der offiziellen Website: https://docs.platformio.org/en/latest/plus/check-tools/pvs-studio.html

Schließlich können Sie eine Projektprüfung mit einem Befehl im Terminal ausführen. Vor dem ersten Test lädt die Umgebung selbst die aktuelle Analysatorverteilung herunter.

pio check

Das Ergebnis der Überprüfung des Hexapod-Programms


Dieses Mal ist es das Ziel des Artikels, die Integration von PVS-Studio in PlatformIO zu demonstrieren und nicht die Diagnosefunktionen des Analysators zu demonstrieren. Berücksichtigen Sie jedoch nach Überprüfung des Projekts einige gefundene Fehler, um zu zeigen, dass das Projekt erfolgreich analysiert wurde.

V519 Links und rechts vom Operator '-' befinden sich identische Unterausdrücke: pow (t, 2) - pow (t, 2). AP_Utils.cpp 176

pointLeg* AP_Utils::traceLeg(uint8_t leg, float phi, float z,
  int resolution, uint8_t shape) {
  ....
  if(shape == ELLIPTIC) {
    ....
    float v = sqrt(pow(phi - legs[leg].phi, 2) + pow(z - legs[leg].z, 2));
    float u = sqrt(pow(phi - phi0, 2) + pow(z - z0, 2));
    float t = sqrt(pow(phi0 - legs[leg].phi, 2) + pow(z0 - legs[leg].z, 2));
    theta = acos((pow(t, 2) - pow(t, 2) - pow(v, 2))/(-2.0*t*u));
    ....
  }
  ....
}

Zwei identische Ausdrücke werden voneinander subtrahiert. Es ist unklar, welche mathematische Bedeutung dieser Unterschied hat. Vielleicht hat der Programmierer den Ausdruck einfach nicht reduziert. Oder vielleicht ist ein Tippfehler erlaubt, und ein anderes Argument muss anstelle eines dieser t sein .

V550 Ein merkwürdig präziser Vergleich: Wert! = - 1. Es ist wahrscheinlich besser, einen Vergleich mit definierter Genauigkeit zu verwenden: fabs (A - B)> Epsilon. AP_Utils.cpp 574

float AP_Utils::sr04_average(uint8_t trig, uint8_t echo,
  int unit, int samples, int time) {
  ....
  float average, pause, value;
  ....
  for(int i=0; i<samples; i++) {
    value = sr04(trig, echo, unit);
    if(value != -1) { // <=
      total += value;
      delay(pause);
    } else {
      i--;
    }
  }
  average = total/samples;
  ....
  return average;
}

Eine Warnung zeigt einen ungenauen Vergleich von Gleitkommazahlen an. Aufgrund der Unmöglichkeit einer genauen Darstellung von reellen Zahlen durch eine endliche Anzahl von Bits ist es sicherer, die Gleichheit von Bruchzahlen durch Vergleichen ihrer Differenz mit einem gegebenen Genauigkeitsindex festzustellen. Zum Beispiel so etwas:

bool is_equal(double x, double y) {
  return std::fabs(x - y) < 0.001f;
}

Die einzig sichere Möglichkeit, nicht ganzzahlige Zahlen direkt zu vergleichen, besteht darin, den Variablen Konstanten zuzuweisen und ihre Werte dann mit diesen Konstanten zu vergleichen. In diesem Fall ist der Wert des Variablenwerts an einer beliebigen Stelle nicht speziell -1 zugeordnet. So funktioniert die aufgerufene Methode AP_Utils :: sr04 , die den überprüften Wert zurückgibt:

float AP_Utils::sr04(uint8_t trig, uint8_t echo, int unit) {
  ....
  float duration, distance;
  ....
  duration = pulseIn(echo, HIGH);
  distance = (346.3*duration*0.000001*unit)/2; // <=
  
  if((distance >= 0.02*unit) && (distance <= 4*unit)) {
    ....
    return(distance);
  } else {
    ....
    return 0;
  }
}

Wie Sie sehen können, wird der Wert als Ergebnis einiger Berechnungen geschrieben. Die Zuweisung -1 ist nirgends zu sehen, aber AP_Utils :: sr04 kann 0 zurückgeben, was darauf hindeutet, dass der Vergleich nicht mit dem Ergebnis durchgeführt wird.

Fazit


In diesem Artikel haben wir den Prozess der Überprüfung von Projekten auf Mikrocontrollern mit einem statischen Code-Analysator in der Programmierumgebung für eingebettete PlatformIO-Systeme untersucht. Ich möchte Sie daran erinnern, dass jeder, der PVS-Studio ausprobieren möchte, den Testmodus verwenden kann. Für offene Projekte besteht die Möglichkeit, eine kostenlose Lizenz zu erhalten .

Für diejenigen, die mehr über die Funktionen von PVS-Studio erfahren möchten, empfehle ich die folgenden Artikel:




Wenn Sie diesen Artikel einem englischsprachigen Publikum zugänglich machen möchten, verwenden Sie bitte den Link zur Übersetzung: Alexey Govorov. PVS-Studio-Integration in PlatformIO .

All Articles