Detección de código muerto en el proyecto heredado C/C++
automation static-analysis (8)
¿Cómo haría para detectar el código muerto en el código C / C ++? Tengo una base de código bastante grande para trabajar y al menos un 10-15% es código inactivo. ¿Hay alguna herramienta basada en Unix para identificar estas áreas? Algunas piezas de código todavía usan mucho preprocesador, ¿puede el proceso automatizado manejar eso?
Compilar bajo gcc con -Wunreachable-code.
Creo que cuanto más reciente sea la versión, mejores resultados obtendrás, pero puedo estar equivocado en mi impresión de que es algo en lo que han estado trabajando activamente. Tenga en cuenta que este análisis de flujo, pero no creo que le dice acerca de "código" que ya está muerto en el momento en que deja el preprocesador, porque eso nunca es analizado por el compilador. Tampoco detectará, por ejemplo, las funciones exportadas que nunca se llaman, o el código especial de manejo de casos que simplemente resulta imposible porque nada llama a la función con ese parámetro; necesita cobertura de código para eso (y ejecuta las pruebas funcionales, no las pruebas unitarias. Se supone que las pruebas unitarias tienen una cobertura de código del 100% y, por lo tanto, ejecutan rutas de código que están "muertas" en lo que respecta a la aplicación). Aún así, teniendo en cuenta estas limitaciones, es una manera fácil de empezar a buscar las rutinas más completas de la base de códigos.
Este aviso CERT enumera algunas otras herramientas para detección de código muerto estático
El análisis de código muerto como este requiere un análisis global de todo su proyecto. No puede obtener esta información analizando individualmente las unidades de traducción (bueno, puede detectar entidades muertas si están completamente dentro de una sola unidad de traducción, pero no creo que eso sea lo que realmente está buscando).
Hemos utilizado nuestro Software de reingeniería de software DMS para implementar exactamente esto para el código de Java, al analizar todas las unidades de compilación involucradas a la vez, crear tablas de símbolos para todo y buscar todas las referencias. Una definición de nivel superior sin referencias y sin reclamo de ser un elemento API externo está muerta. Esta herramienta también elimina automáticamente el código muerto, y al final puede elegir lo que desea: el informe de entidades muertas, o el código desprovisto de esas entidades.
DMS también analiza C ++ en una variedad de dialectos (EDITAR Feb 2014: incluye versiones MS y GCC de C ++ 14 [EDIT Nov 2017: ahora C ++ 17] ) y crea todas las tablas de símbolos necesarias. Rastrear las referencias muertas sería sencillo desde ese punto. DMS también podría usarse para eliminarlos. Ver http://www.semanticdesigns.com/Products/DMS/DMSToolkit.html
Puede utilizar una herramienta de análisis de cobertura de código para esto y buscar lugares no utilizados en su código.
Una herramienta popular para la cadena de herramientas gcc es gcov, junto con la interfaz gráfica lcov ( http://ltp.sourceforge.net/coverage/lcov.php ).
Si usa gcc, puede compilar con soporte de gcov, que está habilitado por el indicador ''--coverage''. A continuación, ejecute su aplicación o ejecute su suite de prueba con esta versión habilitada para gcov.
Básicamente, gcc emitirá algunos archivos adicionales durante la compilación y la aplicación también emitirá algunos datos de cobertura mientras se ejecuta. Tienes que recolectar todos estos (archivos .gcdo y .gcda). No voy a entrar en detalles aquí, pero probablemente deba establecer dos variables de entorno para recopilar los datos de cobertura de una manera sensata: GCOV_PREFIX y GCOV_PREFIX_STRIP ...
Después de la ejecución, puede juntar todos los datos de cobertura y ejecutarlos a través de lcov toolsuite. También es posible fusionar todos los archivos de cobertura de diferentes ejecuciones de prueba, aunque sea un poco complicado.
De todos modos, terminas con un buen conjunto de páginas web que muestran cierta información de cobertura, señalando los fragmentos de código que no tienen cobertura y, por lo tanto, no se usaron.
Por supuesto, debe verificar si las partes del código no se usan en ninguna situación y mucho depende de qué tan buenas sean las pruebas que ejercen la base de código. Pero al menos, esto dará una idea sobre posibles candidatos de código muerto ...
Solo para el código C y suponiendo que el código fuente de todo el proyecto esté disponible, inicie un análisis con la herramienta de código abierto Frama-C . Cualquier declaración del programa que se muestra en rojo en la GUI es un código muerto.
Si tiene problemas con el "código muerto", también puede estar interesado en eliminar el "código de repuesto", código que se ejecuta pero que no contribuye al resultado final. Esto requiere que proporciones una modelización precisa de las funciones de E / S (no querrás eliminar un cálculo que parece ser "de repuesto" pero que se usa como argumento para printf
). Frama-C tiene una opción para señalar el código de repuesto.
Su enfoque depende de las pruebas de disponibilidad (automatizadas). Si tiene un conjunto de pruebas en el que confía para cubrir una cantidad suficiente de funcionalidad, puede usar un análisis de cobertura, como ya se sugirieron las respuestas anteriores.
Si no eres tan afortunado, tal vez quieras buscar herramientas de análisis de código fuente como SciTools ''Understand que te pueda ayudar a analizar tu código usando muchos informes de análisis integrados. Mi experiencia con esa herramienta data de hace 2 años, así que no puedo darle muchos detalles, pero lo que sí recuerdo es que tuvieron un apoyo impresionante con plazos de respuesta muy rápidos para corregir errores y respuestas a preguntas.
Encontré una página en el análisis de código fuente estático que enumera muchas otras herramientas también.
Si eso no te ayuda lo suficiente tampoco, y estás específicamente interesado en descubrir el código muerto relacionado con el preprocesador, te recomendaría que publicaras más detalles sobre el código. Por ejemplo, si está relacionado principalmente con varias combinaciones de configuraciones #ifdef, podría escribir scripts para determinar las (combinaciones de) configuraciones y descubrir qué combinaciones nunca están realmente construidas, etc.
Tanto Mozilla como Open Office tienen soluciones propias.
g ++ 4.01 - Código inalcanzable advierte sobre el código que no se puede alcanzar dentro de una función, pero no advierte sobre las funciones no utilizadas.
int foo() {
return 21; // point a
}
int bar() {
int a = 7;
return a;
a += 9; // point b
return a;
}
int main(int, char **) {
return bar();
}
g ++ 4.01 emitirá una advertencia sobre el punto b, pero no dice nada acerca de foo () (punto a) aunque no esté accesible en este archivo. Este comportamiento es correcto aunque decepcionante, porque un compilador no puede saber que la función foo () no se declara externamente en alguna otra unidad de compilación y se invoca desde allí; solo un enlazador puede estar seguro.