c++ - reglas - sonar software
¿Las herramientas de análisis de código estático de C++ valen la pena? (14)
Ayuda Yo sugeriría que tomes una versión de prueba y la ejecutes en una parte de tu código base que crees que está descuidado. Estas herramientas generan muchos falsos positivos. Una vez que haya revisado estos, es probable que encuentre uno o dos atiborrados de búfer que pueden ahorrar mucho dolor en un futuro cercano. Además, pruebe al menos dos / tres variedades (y también algunas de las cosas de OpenSource).
Nuestra administración ha estado hablando recientemente con algunas personas que venden herramientas de análisis estático de C ++. Por supuesto, los vendedores dicen que encontrarán toneladas de errores, pero soy escéptico.
¿Cómo funcionan estas herramientas en el mundo real? ¿Encuentran errores reales? ¿Ayudan a los programadores más jóvenes a aprender?
¿Valen la pena el problema?
Como comentó un par de personas, si ejecuta una herramienta de análisis estático en la mayoría de las aplicaciones, recibirá muchas advertencias, algunas de ellas pueden ser falsos positivos o no dar lugar a un defecto explotable. Es esa experiencia la que nos lleva a la percepción de que este tipo de herramientas son ruidosas y quizás una pérdida de tiempo. Sin embargo, hay advertencias que resaltarán defectos reales y potencialmente peligrosos que pueden conducir a problemas de seguridad, confiabilidad o corrección y, para muchos equipos, estos problemas son importantes para solucionar y pueden ser casi imposibles de descubrir a través de pruebas.
Dicho esto, las herramientas de análisis estático pueden ser muy útiles, pero aplicarlas a un código base existente requiere una pequeña estrategia. Aquí hay un par de consejos que podrían ayudarte.
1) No encienda todo de una vez, decida sobre un conjunto inicial de defectos, encienda esos análisis y repárelos en su base de código.
2) Cuando aborde una clase de defectos, ayude a todo su equipo de desarrollo a comprender cuál es el defecto, por qué es importante y cómo codificar para defenderse contra ese defecto.
3) Trabajar para borrar completamente la base de código de esa clase de defectos.
4) Una vez que se haya solucionado esta clase de problemas, introduzca un mecanismo para permanecer en ese estado de cero problemas. Afortunadamente, es mucho más fácil asegurarse de que no esté reintroduciendo un error si está en una línea de base, no tiene errores.
Como con todo, la respuesta depende ... si usted es el único desarrollador que trabaja en una impresora de patrones de punto para su abuela, es probable que no quiera comprar ninguna herramienta de análisis estático. Si tiene un proyecto de software de tamaño mediano que se integrará en algo importante y tal vez, además de eso, tenga un calendario apretado, es posible que desee invertir un poco ahora, lo que le ahorrará mucho más en el futuro.
Recientemente escribí una diatriba general sobre esto: http://www.redlizards.com/blog/?p=29
Debería escribir la parte 2 tan pronto como el tiempo lo permita, pero en general hacer algunos cálculos aproximados para ver si vale la pena:
- ¿Cuánto tiempo pasó en la depuración?
- ¿Cuántos recursos atados?
- ¿Qué porcentaje podría haber sido encontrado por análisis estático?
- costos para la configuración de la herramienta?
- ¿precio de compra?
- ¿tranquilidad de espíritu? :-)
Mi toma personal también es:
obtener análisis estático a principios de
- temprano en el proyecto
- temprano en el ciclo de desarrollo
- temprano como muy temprano (antes de la construcción nocturna y las pruebas posteriores)
proporcionar al desarrollador la capacidad de utilizar el análisis estático por sí mismo
- A nadie le gusta que los ingenieros de pruebas o alguna herramienta anónima le digan lo que hicieron mal ayer.
- menos depuración hace feliz a un desarrollador :-)
- proporciona una buena manera de aprender sobre las trampas (sutiles) sin vergüenza
Creo que el análisis de código estático vale la pena, si está utilizando la herramienta correcta. Recientemente, probamos la herramienta Coverity (un poco caro). Es impresionante, sacó muchos defectos críticos, que no fueron detectados por la pelusa o la purificación.
También encontramos que, podríamos haber evitado el 35% de los defectos de campo del cliente, si hubiésemos utilizado la cobertura antes.
Ahora, Coverity se implementa en mi compañía y, cuando alguna vez obtenemos TR de un cliente en una versión anterior del software, estamos corriendo en contra de ella para sacar a los candidatos potenciales a la falla antes de comenzar el análisis en un sistema de suscripción.
El análisis de código estático casi siempre vale la pena. El problema con una base de código existente es que probablemente informe demasiados errores para que sea útil de manera inmediata.
Una vez trabajé en un proyecto que tenía más de 100.000 advertencias del compilador ... no tiene sentido ejecutar herramientas de Lint en esa base de código.
Usar las herramientas de Lint "a la derecha" significa comprar en un proceso mejor (lo cual es algo bueno). Uno de los mejores trabajos que tuve fue trabajar en un laboratorio de investigación donde no se nos permitió verificar el código con advertencias.
Entonces, sí, las herramientas valen la pena ... a largo plazo. En el corto plazo, gire las advertencias de su compilador al máximo y vea lo que informa. Si el código está "limpio", el momento de mirar las herramientas de pelusa es ahora. Si el código tiene muchas advertencias ... priorícelas y corrígelas. Una vez que el código no tenga ninguna advertencia (o al menos muy pocas), consulte las herramientas de Lint.
Por lo tanto, las herramientas de Lint no van a ayudar a una base de código pobre, pero una vez que tenga una buena base de código, puede ayudarlo a mantenerse en buen estado.
Editar:
En el caso del producto de advertencia de más de 100,000, se dividió en aproximadamente 60 proyectos de Visual Studio. Como se eliminaron todas las advertencias de cada proyecto, se modificaron para que las advertencias fueran errores, lo que impidió que se agregaran nuevas advertencias a los proyectos que se habían limpiado (o, más bien, dejó que mi compañero de trabajo gritara correctamente a cualquier desarrollador que se registrara). Código sin compilarlo primero :-)
El análisis estático que encuentra errores reales lo vale independientemente de si es C ++ o no. Algunos tienden a ser bastante ruidosos, pero si pueden detectar errores sutiles como las comparaciones firmadas / no firmadas que causan optimizaciones que rompen el código o los accesos de matriz fuera de límites, definitivamente valen la pena.
En mi experiencia con un par de empleadores, Coverity Prevent para C / C ++ definitivamente valió la pena, encontrando algunos errores incluso en el código de los buenos desarrolladores, y muchos errores en el código de los peores desarrolladores. Otros ya han cubierto aspectos técnicos, así que me centraré en las dificultades políticas.
Primero, los desarrolladores cuyo código necesita el análisis estático, son los menos propensos a usarlo voluntariamente. Por lo tanto, me temo que necesitará un sólido respaldo administrativo, tanto en la práctica como en la teoría; de lo contrario, podría terminar como un elemento de la lista de verificación, para producir métricas impresionantes sin que realmente se corrijan los errores. Cualquier herramienta de análisis estático producirá falsos positivos; es probable que deba dedicar a alguien a minimizar la molestia de ellos, por ejemplo, mediante la determinación de defectos, priorizando las fichas y ajustando la configuración. (Una herramienta comercial debe ser extremadamente buena para que nunca muestre un falso positivo más de una vez, ya que solo puede valer la pena el precio). Incluso los defectos genuinos pueden generar molestia; Mi consejo sobre este tema es que no se preocupe, por ejemplo, los comentarios de verificación quejándose de que los errores obviamente destructivos son "menores".
Mi consejo más importante es un corolario de mi primera ley, arriba: primero toma las fotos baratas y mira los errores dolorosamente obvios de tus peores desarrolladores. Algunos de estos podrían haber sido encontrados por las advertencias del compilador, pero muchos errores pueden pasar por esas grietas, por ejemplo, cuando son suprimidos por opciones de línea de comandos. Los errores realmente flagrantes pueden ser políticamente útiles, por ejemplo, con una lista de los diez mejores de los defectos más divertidos, que pueden concentrar las mentes maravillosamente, si se usan con cuidado.
En un antiguo empleador, teníamos asegurado ++. Ayudó a identificar el comportamiento aleatorio (uso de material no inicializado) que Valgrind no pudo encontrar. Pero lo más importante: ayudó a eliminar errores que aún no se conocían como errores.
Asegurar ++ es bueno, pero caro, es por eso que compramos una licencia de usuario solamente.
Esas herramientas ayudan. lint ha sido una gran herramienta para los desarrolladores de C
Pero una objeción que tengo es que son procesos por lotes que se ejecutan después de haber escrito una buena cantidad de código y generar potencialmente muchos mensajes.
Creo que un mejor enfoque es construir tal cosa en su IDE y hacer que señale el problema mientras lo está escribiendo para que pueda corregirlo de inmediato. No dejes que esos problemas entren en el código base en primer lugar.
Esa es la diferencia entre la herramienta de análisis estático FindBugs para Java y el Inspector de IntelliJ. Yo prefiero mucho a este último.
Este sorprendente resultado se logró utilizando Elsa y Oink.
http://www.cs.berkeley.edu/~daw/papers/fmtstr-plas07.pdf
"Análisis a gran escala de Vulnerabilidades de cadena de formato en Debian Linux" por Karl Chen, David Wagner, UC Berkeley, {quarl, daw}@cs.berkeley.edu
Abstracto:
Los errores de cadena de formato son una vulnerabilidad de seguridad relativamente común y pueden llevar a la ejecución de código arbitrario. En colaboración con otros, diseñamos e implementamos un sistema para eliminar las vulnerabilidades de las cadenas de formato de toda una distribución de Linux, usando la inferencia de typecali, una técnica de análisis estático que puede encontrar violaciones de corrupción. Analizamos con éxito el 66% de los paquetes fuente de C / C ++ en la distribución Debian 3.1 de Linux. Nuestro sistema encuentra 1.533 advertencias de corrupción de cadenas de formato. Estimamos que el 85% de estos son verdaderos positivos, es decir, errores reales; ignorando los duplicados de las bibliotecas, alrededor del 75% son errores reales. Sugerimos que existe la tecnología para hacer que las vulnerabilidades de las cadenas de formato se extingan en un futuro próximo.
Categorías y Descriptores de Sujetos D.4.6 [Sistemas Operativos]: Seguridad y Protección: Software Invasivo; Términos Generales: Seguridad, Idiomas; Palabras clave: vulnerabilidad de cadena de formato, análisis a gran escala, inferencia de tipos de letra
Los he usado - PC-Lint, por ejemplo, y encontraron algunas cosas. Normalmente, son configurables y puedes decirles ''deja de molestarme por xyz'', si determinas que xyz realmente no es un problema.
No sé si ayudan a los programadores junior a aprender mucho, pero pueden usarse como un mecanismo para ayudar a reforzar el código.
Descubrí que un segundo conjunto de ojos (escépticos, sondeo para detectar errores) y pruebas de unidad es normalmente donde he visto que tiene lugar más captura de errores.
Pagar por la mayoría de las herramientas de análisis estático es probablemente innecesario cuando hay algunas gratuitas de muy buena calidad (a menos que necesite alguna característica muy especial o específica provista por una versión comercial). Por ejemplo, vea esta respuesta que le di en otra pregunta sobre cppcheck .
Probablemente tenga que lidiar con una buena cantidad de falsos positivos, particularmente si su código base es grande.
La mayoría de las herramientas de análisis estático funcionan con "análisis intra-procedimentales", lo que significa que consideran cada procedimiento de forma aislada, a diferencia del "análisis de todo el programa" que considera todo el programa.
Por lo general, utilizan el análisis "intra-procedimiento" porque el "análisis de todo el programa" tiene que considerar muchos caminos a través de un programa que en realidad nunca ocurrirá en la práctica y, por lo tanto, a menudo puede generar resultados falsos positivos.
El análisis interno del procedimiento elimina esos problemas al centrarse en un solo procedimiento. Sin embargo, para que funcionen, generalmente necesitan introducir un "lenguaje de anotación" que se usa para describir los metadatos para los argumentos de procedimiento, los tipos de devolución y los campos de objeto. Para C ++, esas cosas generalmente se implementan a través de macros con las que decoras las cosas. Las anotaciones luego describen cosas como "este campo nunca es nulo", "este búfer de cadena está protegido por este valor entero", "este campo solo puede accederse mediante el hilo etiquetado como ''fondo''", etc.
La herramienta de análisis tomará las anotaciones que proporcione y verificará que el código que escribió en realidad se ajuste a las anotaciones. Por ejemplo, si potencialmente puede pasar un valor nulo a algo que está marcado como no nulo, marcará un error.
En ausencia de anotaciones, la herramienta debe suponer lo peor y, por lo tanto, informará una gran cantidad de errores que en realidad no son errores.
Como parece que ya no está utilizando una herramienta de este tipo, debe asumir que tendrá que pasar una cantidad considerable de tiempo anotando su código para deshacerse de todos los falsos positivos que se informarán inicialmente. Inicialmente ejecutaría la herramienta y contaría el número de errores. Eso debería darte una estimación del tiempo que necesitarás para adoptarlo en tu código base.
Si la herramienta vale la pena o no, depende de su organización. ¿Cuáles son los tipos de errores que más te pican? ¿Son errores de desbordamiento del búfer? ¿Son errores de falta de referencia o pérdida de memoria? ¿Están enhebrando problemas? ¿Son "oops, no consideramos ese escenario" o "no probamos una versión china de nuestro producto que se ejecuta en una versión lituana de Windows 98?".
Una vez que descubra cuáles son los problemas, entonces debe saber si vale la pena el esfuerzo.
La herramienta probablemente ayudará con el desbordamiento del búfer, la anulación de nulos y los errores de pérdida de memoria. Existe la posibilidad de que pueda ayudar con el roscado de errores si tiene soporte para el "coloreado de hilos", los "efectos" o el análisis de "permisos". Sin embargo, esos tipos de análisis son bastante vanguardistas y tienen GRANDES cargas de notación, por lo que tienen algún costo. La herramienta probablemente no ayudará con ningún otro tipo de errores.
Por lo tanto, realmente depende del tipo de software que escriba y del tipo de error con el que se encuentre más frecuentemente.
Supongo que depende mucho de tu estilo de programación. Si está escribiendo principalmente código C (con la característica de C ++ ocasional), estas herramientas probablemente podrán ayudar (por ejemplo, administración de memoria, sobrecargas de búfer, ...). Pero si está utilizando funciones de C ++ más sofisticadas, entonces las herramientas pueden confundirse al intentar analizar su código fuente (o simplemente no encontrarán muchos problemas porque las instalaciones de C ++ generalmente son más seguras de usar).