Integración de PVS-Studio en PlatformIO

Cuadro 5

Recientemente, en el entorno de desarrollo del sistema integrado PlatformIO, ha aparecido la compatibilidad con PVS-Studio. En este artículo, aprenderá cómo probar su código con un analizador estático utilizando un proyecto abierto como ejemplo.

¿Qué es PlatformIO?


PlatformIO es una herramienta de programación de microcontroladores multiplataforma. El núcleo de PlatformIO es una herramienta de línea de comandos, pero se recomienda usarlo como un complemento para Visual Studio Code. Se admite una gran cantidad de chips modernos y placas base basadas en ellos. Es capaz de descargar automáticamente sistemas de ensamblaje adecuados, y el sitio tiene una gran colección de bibliotecas para administrar componentes electrónicos enchufables. Hay soporte para varios analizadores de código estático, incluido PVS-Studio.

Proyecto de importación


Para demostrarlo, tomemos el ArduPod hexápodo programa de control de la placa Arduino Mega.


Cree un nuevo proyecto para una placa adecuada y copie el código fuente:

Imagen 2

En la carpeta / arduino / AP_Utils / examples / hay varios ejemplos de programas para configurar y ejecutar el hexapod, usaremos servo_test.ino. El programa para Arduino, por regla general, se crea en forma de bocetos en el formato INO, que en este caso no es del todo adecuado. Para crear un archivo .cpp correcto, generalmente es suficiente cambiar la extensión del nombre del archivo, agregar el encabezado #include <Arduino.h> al principio y asegurarse de que las funciones y las variables globales estén declaradas antes de acceder a ellas.

Cuadro 3

Durante el proceso de ensamblaje, pueden producirse errores por la falta de bibliotecas de terceros requeridas. Sin embargo, PlatformIO lo ayudará a encontrarlos en su repositorio.

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.

El enlace mostrará las opciones apropiadas, y la instalación de la dependencia se realiza con un comando en la terminal:

pio lib install "Adafruit PWM Servo Driver Library"

Configurar analizadores e iniciar una prueba


Para configurar los analizadores, debe editar la configuración de platformio.ini de esta manera:

[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

El parámetro check_tool indica qué analizadores de código usar, y su configuración se realiza en el parámetro check_flags . Se pueden encontrar instrucciones más detalladas en la documentación en el sitio web oficial: https://docs.platformio.org/en/latest/plus/check-tools/pvs-studio.html

Finalmente, puede ejecutar una verificación de proyecto con un comando en el terminal. Antes de la primera prueba, el entorno mismo descarga la distribución actual del analizador.

pio check

El resultado de verificar el programa hexapod


Esta vez, el objetivo del artículo es demostrar la integración de PVS-Studio con PlatformIO, y no demostrar las capacidades de diagnóstico del analizador. Sin embargo, una vez que el proyecto ha sido verificado, considere un par de errores encontrados para mostrar que el proyecto fue analizado con éxito.

V519 Hay subexpresiones idénticas a la izquierda y a la derecha del operador '-': 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));
    ....
  }
  ....
}

Dos expresiones idénticas se restan una de la otra. No está claro cuál es el significado matemático de esta diferencia. Quizás el programador simplemente no redujo la expresión. O tal vez se permite un error tipográfico, y otro argumento debe estar en lugar de uno de estos t .

V550 Una comparación precisa impar: valor! = - 1. Probablemente sea mejor usar una comparación con precisión definida: 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;
}

Una advertencia indica una comparación inexacta de números de coma flotante. Debido a la imposibilidad de una representación precisa de números reales por un número finito de bits, es más seguro establecer la igualdad de números fraccionarios comparando su diferencia con un índice de precisión dado. Por ejemplo, algo como esto:

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

La única opción segura para comparar directamente números no enteros es asignar constantes a las variables y luego comparar sus valores con estas constantes. En este caso, el valor de la variable de valor en cualquier lugar no asignado específicamente -1. Así es como funciona el método llamado AP_Utils :: sr04 , que devuelve el valor marcado:

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;
  }
}

Como puede ver, el valor se escribe como resultado de algunos cálculos. La asignación -1 no se ve en ninguna parte, pero AP_Utils :: sr04 puede devolver 0, y esto sugiere que la comparación no se realiza con el resultado.

Conclusión


En este artículo, examinamos el proceso de verificación de proyectos en microcontroladores con un analizador de código estático en el entorno de programación para sistemas PlatformIO integrados. Permítame recordarle que todos los que quieran probar PVS-Studio pueden usar el modo de prueba , y para proyectos abiertos existe la oportunidad de obtener una licencia gratuita .

Para aquellos que quieran aprender más sobre las características de PVS-Studio con más detalle, les aconsejo que miren los siguientes artículos:




Si desea compartir este artículo con una audiencia de habla inglesa, utilice el enlace a la traducción: Alexey Govorov. Integración PVS-Studio en PlatformIO .

All Articles