¿Hay alguna manera de recibir una advertencia sobre las funciones no utilizadas?

7 minutos de lectura

avatar de usuario
timoteo jones

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.

Aquí hay un ejemplo:

foo.c (asumir apropiado 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 recibir una advertencia sobre foo() no siendo usado

Ahí está el -Wunused-function opción gcc:

-Wunused-function

Avise cada vez que se declare una función estática pero no se defina o cuando no se utilice una función estática no en línea. Esta advertencia está habilitada por -Wall.

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

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

  • Hay una buena razón para no advertir sobre funciones no estáticas no utilizadas de forma predeterminada. 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 quien enlace con la biblioteca. Dicho esto, esta sigue siendo una gran pregunta, que espero tenga una respuesta útil.

    – Adam Mihalcin

    1 de febrero de 2012 a las 5:52


  • Absolutamente, no debería estar activado de forma predeterminada. Aún así, me gustaría poder activarlo en el momento del enlace final si la función existe 🙂

    – Timoteo Jones

    1 de febrero de 2012 a las 5:53


  • Pertinente gcc.gnu.org/ml/gcc-help/2003-08/msg00072.html ?

    – Abhijeet Rastogi

    1 de febrero de 2012 a las 5:55

  • Podría considerar usar una herramienta de cobertura de código 🙂

    – Billy ONeal

    1 de febrero de 2012 a las 5:59

  • Puede probar y compilar todos sus archivos a la vez usando -fwhole-program; tal vez eso le dará advertencias adicionales.

    – KerrekSB

    1 de febrero de 2012 a las 6:05

avatar de usuario
coren

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 y métodos no utilizados en LibreOffice. Su herramienta es un elemento clave para eliminarlos.

Se llama receptor de llamadas. Puede

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

Funciona directamente en la salida del ensamblador y, por lo tanto, solo funciona para la arquitectura x86 y x86_64. Puede producir resultados como esta. Puede integrarlo con su llamada tradicional de compilación y enlace a gcc.

Caolan está de acuerdo en que debería convertirse en un complemento de gcc.

  • Esto hace exactamente lo que quiero, fuera de la caja. ¡Gracias!

    – Timoteo Jones

    21 de febrero de 2012 a las 5:45

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

    – Greg Hewgill

    2 de marzo de 2012 a las 2:17


  • El enlace original está muerto. Esta parece ser la herramienta de referencia. github.com/caolanm/callcatcher

    – Taekahn

    8 de agosto de 2018 a las 21:24

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

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

De la página man de gcc:

–gc-secciones
–no-gc-sections Habilita la recolección de elementos no utilizados de las secciones de entrada no utilizadas. Se ignora en destinos 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-secciones decide qué secciones de entrada se utilizan mediante el examen de símbolos y reubicaciones. La sección que contiene el símbolo de entrada y todas las secciones que contienen símbolos no definidos en la línea de comandos se mantendrán, al igual que las secciones que contienen símbolos a los que hacen referencia los objetos dinámicos. Tenga en cuenta que al crear bibliotecas compartidas, el enlazador debe suponer que se hace referencia a cualquier símbolo visible. Una vez que se ha determinado este conjunto inicial de secciones, el enlazador marca recursivamente como usada cualquier sección referenciada por sus reubicaciones. Consulte –entry y –undefined.

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 guardados debe especificarse explícitamente mediante una opción –entry o –undefined o mediante un comando “ENTRY” en el script del enlazador.

  • Lamentablemente, no estoy buscando eliminar el código del binario; estoy buscando averiguar qué partes de la fuente se pueden limpiar

    – Timoteo Jones

    15 de febrero de 2012 a las 3:28

  • Si no recuerdo mal, hay una opción de verbosidad que imprimirá una lista de optimizaciones realizadas por gc-sections. Creo que es “–print-gc-sections”

    – yalmo

    15 de febrero de 2012 a las 5:13

  • @eyalm, creo que su respuesta obtendrá muchos más votos a favor si la cambia un poco para agregar la opción imprimir-gc-secciones con un ejemplo.

    – Hola angel

    6 de julio de 2018 a las 10:13

avatar de usuario
Basile Starynkevitch

En primer lugar, si desea que dichas advertencias se extiendan a todo el programa, sin duda necesita la -flto bandera, 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, ni siquiera de esta manera.

Entonces, en el caso general, entendería que no sería prudente proporcionarlo (porque, por ejemplo, el enlace libc probablemente tiene muchas funciones que su aplicación no necesita). Además, una aplicación podría usar dlsym trucos para llegar a una función aparentemente no llamada…

Sin embargo, es un buen ejemplo de un caso de uso potencial para un complemento GCC o DERRETIR extension, que registraría cada ocurrencia de llamada en algún lugar, con una utilidad posterior que encontraría todas las funciones no llamadas. (Pero codificar un complemento o una extensión MELT para GCC le llevará al menos varios días, porque necesitará comprender las funciones internas de GCC).

También puede usar técnicas de creación de perfiles para obtener las funciones dinámicamente no utilizadas (no llamadas).

Siéntete libre de preguntarme más por correo electrónico.

  • +1 Gracias. Si termino yendo por la ruta del complemento GCC, es casi seguro que te enviaré un correo electrónico 🙂

    – Timoteo Jones

    1 de febrero de 2012 a las 6:12

  • Estoy mucho más calificado para ayudarlo con las extensiones MELT que con los complementos GCC en C.

    – Basile Starynkevitch

    1 de febrero de 2012 a las 6:19

  • @BasileStarynkevitch: tal vez le interese ver qué ha hecho Caolan Mc Namara al respecto. Ver mi respuesta para más detalles.

    – Coren

    17 de febrero de 2012 a las 8:43

Agregar la opción gcc -ffunction-sections a sus compilaciones, y --gc-sections y --print-gc-sections a su comando de enlace. Si invoca el enlazador a través de gcc, use -Wl,--gc-sections,--print-gc-sections para pasarlos a ld.

Esto eliminará el código de objeto no utilizado, que dijo que no desea. En ese caso, elimine --gc-sections una vez que haya generado la salida deseada.

No preguntó sobre la identificación de datos no utilizados, pero para hacerlo, agregue el -fdata-sections opción a sus compilaciones también.

gprof es la solución más simple, supongo. Compilé el programa de muestra que has aguantado -pg opción para que obtengamos la gmon.out cuando corremos a.out (que gprof puede usar más tarde) y finalmente ejecuté gprof -z a.out gmon.out | tee output.txt . Podría encontrar tu función foo en la lista de no utilizados! es decir, llamado 0 veces. -z es la opción que debe usar junto con gprof para realizar un seguimiento de las rutinas no utilizadas.

Gracias a esta hilo para el puntero apropiado!

PD: gprof arrojó una gran cantidad de otras funciones de biblioteca no utilizadas junto con su función no utilizada foo. En serio, no sé cómo filtrar esto 🙂

avatar de usuario
dbrank0

Eclipse CDT tiene análisis de código, que puede configurar para marcar funciones estáticas no utilizadas y 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 binarios …

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad