2008-10-23 9 views
66

¿Qué le parece la detección de 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?Detección de código muerto en el proyecto heredado de C/C++

+2

Aquí hay una pregunta similar con más actividad aquí: http://stackoverflow.com/questions/4813947/how-can-i-know-which-parts-in-the-code-are-never-used/ –

Respuesta

30

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 poner todos los datos de cobertura juntos y ejecutarlo a través de la herramienta de herramientas lcov. 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 las piezas de código que no tienen cobertura y, por lo tanto, no se utilizaron.

Por supuesto, debe verificar si las partes del código no se usan en ninguna situación y mucho depende de cuán 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 ...

+0

Todavía estoy atascado con los compiladores de Sun C++, pero tenemos la migración de gcc en curso, así que voy a probar esto. Gracias. – Nazgob

+0

El análisis de cobertura de código (como 'gcov') puede proporcionar datos cuyo código no está cubierto por la (s) ejecución (es) particular (es) del software; el código que no está cubierto no es necesariamente un código muerto. Una ejecución diferente del software (como una opción de compilación diferente, una opción de tiempo de ejecución diferente o datos de entrada diferentes) o una ruta de ejecución diferente (como el manejo de errores) puede desencadenar una función que no se invocó antes. – Arun

1

Bullseye herramienta de cobertura ayudaría. Sin embargo, no es gratis.

+0

Is vale dinero? Alguna experiencia con eso? Tienen una versión de prueba así que podría comprobarlo, si funciona, podemos comprarlo :) – Nazgob

+0

Sí .. He usado en la plataforma Symbian ...Definitivamente vale la pena comprarlo – Ashwin

4

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 es tan afortunado, puede consultar las herramientas de análisis de código fuente como SciTools 'Comprenda que puede ayudarle a analizar su 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 static source code analysis que enumera muchas otras herramientas también.

Si eso no te ayuda lo suficiente tampoco, y estás interesado específicamente en conocer 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 configuraciones (combinaciones de) y descubrir qué combinaciones nunca se construyen realmente, etc.

16

Compilarlo en gcc con -Wunreachable -código.

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á, p. funciones exportadas que nunca se llaman, o 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. Las pruebas unitarias son supone tener una cobertura de código del 100% y, por lo tanto, ejecutar 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.

This CERT advisory lists some other tools for static dead code detection

+2

Esta respuesta no es más válida que el hecho de que la opción -Wunreachable-code se eliminó de gcc. http://gcc.gnu.org/ml/gcc-help/2011-05/msg00360.html –

+0

Vergüenza. Para muchos fines, la detección de código muerto "inestable" es mejor que nada. Aparte de todo lo demás, la detección perfecta del código muerto en general es imposible (problema de detención), por lo que todos saben que cualquier herramienta que utilicen es imperfecta. Es de suponer que a alguien realmente le importa que '-O0' sea más imperfecto que con '-O3', o que no quiera nuevas advertencias cada vez que mejore el optimizador. –

+3

Aún así, si su código no utiliza nuevas características, podría usar un gcc antiguo como herramienta de análisis estático. Entonces mi respuesta no es * completamente * incorrecta. Un poco de alcance, lo sé ;-) –

4

Tanto MozillaOpen Office y tienen soluciones locales.

+0

Ambos enlaces son inaccesibles ahora. ¿Alguien puede actualizar? – syam

+1

He cambiado el primer enlace de una publicación de blog a una página de documentación (con suerte más larga). El enlace de Open Office parece funcionar. –

4

g ++ 4.01 -El 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 dicen nada acerca de foo() (punto a) a pesar de que no se puede acceder 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.

3

El análisis de código muerto como este requiere un análisis global de todo el 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 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: including MS and GCC versions of C++14 [EDIT Nov 2017: now C++17]) y construye 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

4

Para único código C y suponiendo que el código fuente de todo el proyecto está disponible, el lanzamiento de un análisis con la herramienta Open Source Frama-C. Cualquier declaración del programa que se muestra en rojo en la GUI es código muerto.

Si tiene problemas con el "código muerto", también puede estar interesado en eliminar el "código de reserva", código que se ejecuta pero no para contribuir al resultado final. Esto requiere que proporcione una modelización precisa de las funciones de E/S (no desea para eliminar un cálculo que parece ser "de repuesto" pero que se utiliza como argumento para printf). Frama-C tiene una opción para señalar el código de repuesto.

Cuestiones relacionadas