2012-02-01 15 views
43

Me gustaría encontrar funciones no utilizadas en una base de código, incluso en unidades de compilación. Estoy usando gcc como mi compilador.¿Hay alguna manera de obtener una advertencia sobre las funciones no utilizadas?

He aquí un ejemplo:

foo.c (asumir apropiada foo.h):

void foo() { 
    .... 
} 

void bar() { 
    .... 
} 

main.c:

#include <stdio.h> 
#include "foo.h" 

int main(void) { 
    bar(); 
    return 0; 
} 

En este ejemplo, me gustaría llegar advertido sobre foo() no estar usado.

Existe la opción -Wunused-function gcc:

-Wunused-function

avise siempre una función estática se declara pero no está definida o una función estática en línea no se utiliza. Esta advertencia es habilitada por -Wall.

pero es solo para funciones estáticas, no aparecerá una advertencia en el ejemplo anterior.

También aceptaré sugerencias de herramientas/scripts/otros compiladores que puedan hacer esto por mí, aunque preferiría seguir con gcc si es posible.

+6

Hay una buena razón para no advertir por defecto las funciones no estáticas. Una función no estática es parte de la interfaz pública, ya que podría alimentar fácilmente un archivo .o generado por gcc a través del enlazador para generar una biblioteca .a o .so en la que todas esas funciones no estáticas estén disponibles para todos los enlaces. con la biblioteca. Dicho esto, esta sigue siendo una gran pregunta, que espero que tenga una respuesta útil. –

+3

Absolutamente, no debería estar activado por defecto. Aún así, me gustaría poder activarlo en el momento del enlace final si la función existe :) –

+1

Relevante http: //gcc.gnu.org/ml/gcc-help/2003-08/msg00072.html? –

Respuesta

41

Caolan Mc Namara, un desarrollador de LibreOffice, ha creado una pequeña herramienta para detectar este tipo de cosas en el código fuente de LibreOffice. Tenían alrededor de miles de funciones & métodos no utilizados en LibreOffice. Su herramienta es un elemento clave para eliminarlos.

Se llama callcatcher. Puede

recoger funciones/métodos definidos y restar llamados/referenciados

que trabaja directamente en la salida del ensamblador y por lo tanto, sólo funciona para x86 y la arquitectura x86_64. Puede producir resultados como this. Puede integrarlo con su compilación tradicional y vincular llamadas a gcc.

Caolan acepta que se convierta en un complemento de gcc.

+0

Esto hace exactamente lo que quiero, listo para usar. ¡Gracias! –

+4

Eso es brillante. Para su valor de entretenimiento, el proyecto en el que estoy trabajando tiene ** 1257 funciones no utilizadas **. Tenía la impresión de que podría haber más de unos pocos en esta base de código ... –

3

En primer lugar, si desea que tales advertencias sean para todo el programa, sin duda necesita el indicador -flto, ya que debe resolverse en el momento del enlace, no en el momento de la compilación de cada unidad individual. Pero no creo que GCC proporcione tales advertencias, incluso de esta manera.

Luego, en el caso general, entiendo que no será conveniente proporcionarlo (porque, por ejemplo, el libc enlazado probablemente tenga muchas funciones que su aplicación no necesita). Además, una aplicación podría utilizar dlsym trucos para llegar a una función aparentemente fuera de lugar ...

Sin embargo, es un buen ejemplo de un caso de uso potencial para un plugin GCC o MELT extensión, lo que registrarse en cada ocurrencia llamada en algún lugar, con una utilidad posterior que encuentra todas las funciones no llamadas. (Pero codificar un complemento o una extensión MELT para GCC te llevará al menos varios días, porque necesitarás entender las partes internas de GCC).

También podría usar técnicas de generación de perfiles para obtener las funciones no utilizadas dinámicamente (no llamadas).

No dudes en preguntarme más por correo electrónico.

+1

+1 Gracias. Si termino yendo a la ruta del complemento de GCC, casi con certeza te enviaré un correo electrónico :) –

+0

Estoy mucho más capacitado para ayudarte en las extensiones MELT que en los complementos de GCC en C. –

+0

@BasileStarynkevitch: tal vez tú Estaré interesado en ver lo que Caolan Mc Namara ha hecho al respecto. Ver mi respuesta para más detalles. – Coren

3

Sé que ha pedido advertencias y prefiere no usar la opción gcc, pero es realmente fácil.

Puede utilizar la optimización del enlazador (--gc-sections) para eliminar el código muerto de su aplicación.

De página del manual de gcc:

--gc secciones --no-GC-secciones habilitar la recogida de basura de las secciones de entrada no utilizados.Se ignora en los objetivos que no admiten esta opción. El comportamiento predeterminado (de no realizar esta recolección de basura) se puede restaurar especificando --no-gc-sections en la línea de comando.

--gc-sections decide qué secciones de entrada se utilizan mediante el examen de símbolos y reubicaciones. Se mantendrá la sección que contiene el símbolo de entrada y todas las secciones que contienen símbolos indefinidos en la línea de comandos, al igual que las secciones que contienen símbolos referenciados por objetos dinámicos. Tenga en cuenta que al compilar bibliotecas compartidas, el vinculador debe suponer que se hace referencia a cualquier símbolo visible. Una vez que se ha determinado este conjunto inicial de secciones, el vinculador marca recursivamente como usado cualquier sección referenciada por sus reubicaciones. Ver --entry y --indefinido.

Esta opción se puede configurar al hacer un enlace parcial (habilitado con la opción -r). En este caso, la raíz de los símbolos mantenidos debe especificarse explícitamente mediante una opción --entry o --undefined o mediante un comando "ENTRY" en el script del enlazador.

+3

Tristemente no estoy buscando eliminar el código del binario - Estoy buscando para averiguar qué partes de la fuente se pueden limpiar –

+5

Si mal no recuerdo, hay una opción de verbosidad que imprimirá una lista de optimizaciones que fue hecho por gc-sections. Creo que es "--print-gc-sections" – eyalm

1

Eclipse CDT tiene un análisis de código, que puede configurar para marcar las funciones estáticas no utilizadas y las declaraciones de funciones no utilizadas (entre otras cosas útiles). Como ya se dijo, solo el enlazador podría decir que cierta función (no estática) no se usó en ciertos archivos binarios ...

1

gprof es la solución más simple, supongo. Recopilé el programa de ejemplo que has puesto con la opción -pg para que obtengamos el gmon.out cuando ejecutamos a.out (que gprof puede usar más adelante) y finalmente ejecuté gprof -z a.out gmon.out | tee output.txt. ¡Pude encontrar tu función foo en la lista no utilizada! es decir, 0 veces. -z es la opción que debe usar junto con gprof para rastrear las rutinas no utilizadas.

¡Gracias a this hilo para el puntero apropiado!

PS: gprof vomitó una serie de otras funciones de la biblioteca no utilizadas junto con su función no utilizada foo. En serio, no sé cómo filtrar esto :)

Cuestiones relacionadas