El análisis estático mejorará la base de código de proyectos complejos de C ++

Viejos grandes proyectos

Poco a poco y discretamente, una situación se desarrolla cuando la complejidad de los proyectos serios de C ++ se vuelve prohibitiva. Desafortunadamente, ahora un programador de C ++ no puede confiar únicamente en sus propias fortalezas.

En primer lugar, hay tanto código que ya no es posible cuando hay al menos un par de programadores en el proyecto que conocen todo el proyecto. Por ejemplo, el kernel de Linux 1.0.0 contenía aproximadamente 176 mil líneas de código. Esto es mucho, pero fue posible colocar una máquina de café cerca y en un par de semanas más o menos mirar todo el código y comprender los principios generales de su funcionamiento. Si tomamos el kernel de Linux 5.0.0, el tamaño de la base de código ya es de aproximadamente 26 millones de líneas de código. El código del núcleo ha crecido casi 150 veces. Solo puede seleccionar varias partes del proyecto y participar en su desarrollo. Es imposible sentarse y descubrir cómo funciona exactamente todo esto, cuáles son las relaciones entre las distintas secciones del código.

En segundo lugar, el lenguaje C ++ continúa evolucionando rápidamente. Por un lado, esto es bueno, ya que hay construcciones que le permiten escribir código más compacto y seguro. Por otro lado, debido a la compatibilidad con versiones anteriores, los grandes proyectos antiguos se vuelven heterogéneos. Entrelazan viejos y nuevos enfoques para escribir código. La analogía con los anillos en una sección de un árbol ruega. Debido a esto, cada año sumergirse en proyectos escritos en C ++ se vuelve cada vez más difícil. Es necesario comprender el código al mismo tiempo, ambos escritos en el estilo C con clases, así como en enfoques modernos (lambdas, semántica de movimiento, etc.). Se necesita demasiado tiempo para aprender completamente C ++. Pero como todavía se requiere para desarrollar proyectos, las personas comienzan a escribir código en C ++ sin haber estudiado todos sus matices hasta el final. Esto conduce a defectos adicionales, pero es irracional debido a esto para detenerse y esperar a que todos los desarrolladores se familiaricen perfectamente con C ++.

¿La situación es desesperada? No Una nueva clase de herramientas viene al rescate: los analizadores de código estático. Muchos programadores experimentados en este momento fruncieron los labios, como si se hubieran deslizado un limón :). Como, sabemos que estas son tus palabras ... Hay muchos mensajes, un poco de sentido ... Sí, ¿y cuál es esta nueva clase de herramientas? Lanzamos Linter hace 20 años.

Sin embargo, me aventuro a afirmar que esta es precisamente una nueva clase de herramientas. Lo que sucedió hace 10-20 años no es en absoluto las herramientas que ahora se llaman analizadores estáticos. Primero, no estoy hablando de herramientas orientadas al formato de código. También se relacionan con herramientas de análisis estático, pero ahora estamos hablando de identificar errores en el código. En segundo lugar, las herramientas modernas utilizan tecnologías de análisis sofisticadas, teniendo en cuenta las interconexiones entre las diferentes funciones y, en realidad, ejecutando virtualmente ciertas secciones de código. Estos no son los mismos linters de 20 años basados ​​en expresiones regulares. Por cierto, no se puede hacer un analizador estático normal en expresiones regulares. Para encontrar errores, se utilizan tecnologías como el análisis de flujo de datos, la anotación automática de métodos, la ejecución simbólica, etc.

Estas no son palabras abstractas, sino la realidad que observo como uno de los creadores de la herramienta PVS-Studio. Consulte este artículo para ver por qué los analizadores pueden encontrar errores interesantes.

Sin embargo, es mucho más importante que los analizadores estáticos modernos tengan un amplio conocimiento de los patrones de error. Además, los analizadores saben más que incluso los desarrolladores profesionales. Se hizo demasiado difícil tener en cuenta y recordar todos los matices al escribir el código. Por ejemplo, a menos que lo lea específicamente en alguna parte, nunca adivinará que las llamadas a la función memset para borrar datos privados a veces desaparecen, ya que desde el punto de vista del compilador, la llamada a la función memset es redundante. Mientras tanto, este es un grave defecto de seguridad CWE-14 , que se encuentra literalmente en todas partes . ¿O quién, por ejemplo, sabe qué es peligroso en el llenado de un recipiente?

std::vector<std::unique_ptr<MyType>> v; v.emplace_back(new MyType(123)); 

Creo que no todos se darán cuenta de inmediato de que dicho código es potencialmente peligroso y puede provocar pérdidas de memoria.

Además del amplio conocimiento de los patrones, los analizadores estáticos son infinitamente atentos y nunca se cansan. Por ejemplo, a diferencia de una persona, no son demasiado vagos para mirar los archivos de encabezado para asegurarse de que isspace y sprintf son funciones reales y no macros locos que estropean todo. Tales casos demuestran la esencia de la dificultad de encontrar errores en proyectos grandes: algo cambia en un lugar, pero se rompe en otro.

Estoy convencido de que pronto el análisis estático se convertirá en una parte integral de DevOps, será tan natural y necesario como el uso del sistema de control de versiones. Esto ya está sucediendo gradualmente en conferencias dedicadas al proceso de desarrollo, donde el análisis estático se menciona cada vez más como una de las primeras líneas de defensa para combatir los errores.

El análisis estático sirve como una especie de filtro grueso. Es ineficiente buscar errores estúpidos y errores tipográficos utilizando pruebas unitarias o pruebas manuales. Es mucho más rápido y económico arreglarlos inmediatamente después de escribir el código, utilizando análisis estático para detectar problemas. Esta idea, así como la importancia del uso regular del analizador, está bien descrita en el artículo " Incruste el análisis estático en el proceso y no busque errores ".

Alguien puede decir que las herramientas especiales no tienen sentido, ya que el compilador también aprende a hacer tales comprobaciones estáticas. Si lo es Sin embargo, los analizadores estáticos, naturalmente, no se detienen y cómo las herramientas especializadas superan a los compiladores. Por ejemplo, cada vez que verificamos LLVM, encontramos errores allí usando PVS-Studio.

El mundo ofrece una gran cantidad de herramientas para el análisis de código estático. Como dicen, elige a tu gusto. ¿Quiere encontrar muchos errores y vulnerabilidades potenciales incluso en la etapa de escribir código? ¡Utilice analizadores de código estático y mejore la calidad de su base de código!



Si desea compartir este artículo con una audiencia de habla inglesa, utilice este enlace: Andrey Karpov. Por qué el análisis estático puede mejorar una base de código compleja de C ++

Source: https://habr.com/ru/post/462399/


All Articles