2009-02-18 12 views
8

Quiero eliminar variables locales sin usar del archivo C. Ejemplo:Eliminación automática de variables locales no utilizadas del código fuente C

int fun(int a , int b) 
{ 
    int c,sum=0; 
    sum=a + b; 
    return sum; 
} 

Aquí la variable no utilizada es 'c'.

I externamente tendré una lista de todas las variables locales no utilizadas. Ahora, utilizando las variables locales no utilizadas que tengo, tenemos que encontrar variables locales del código fuente & eliminar.
En el ejemplo anterior, "c" es una variable no utilizada. Lo sabré (tengo un código para eso). Aquí tengo que encontrar c & eliminarlo.

EDITAR

El punto no es encontrar las variables locales no utilizados con una herramienta externa. El punto es eliminarlos del código dada una lista de ellos.

+0

Por supuesto, se puede ir más lejos, y decir "diversión int (int a, int b) {return a + b;}" y eliminar suma así. Pero esa no era tu pregunta. –

+0

¿Cuál es el formato de lista de variables no utilizadas que tiene? ¿Tiene números de línea y columna? – Constantin

+0

¿por qué quieres hacer eso? ¿Qué le impide borrar manualmente las variables no utilizadas tan pronto como no se utilizan? ¿O tus colegas los colocan deliberadamente en el código y te dicen que los elimines con una lista? –

Respuesta

20

Suba el nivel de advertencia del compilador, y debería decirle.

Poner su fragmento de la fuente en "f.c":

% gcc -c -Wall f.c 
f.c: In function 'fun': 
f.c:1: warning: unused variable 'c' 
+0

¡Ningún punto en esto! ¡La pregunta asume que ya tienes esta lista! Y gcc no viene con una opción -Wjustfixit. – MSalters

+1

Sí, sí, compare la salida de -O0 y -O1 :) – Christoffer

+1

Sí, un compilador decente hará un análisis estático y determinará si puede eliminar la declaración de variable de la salida. –

-1

también: splint.

Splint es una herramienta para chequear estáticamente los programas C por vulnerabilidades de seguridad y errores de codificación. Con un esfuerzo mínimo, Splint se puede utilizar como una mejor pelusa. Si se invierte esfuerzo adicional al agregar anotaciones a los programas, Splint puede realizar una comprobación más sólida que la que puede hacerse con cualquier pelusa estándar.

1

Además de ser capaz de revelar esto a través de las advertencias, el compilador normalmente las optimizará si se activan las optimizaciones. Comprobar si una variable nunca se referencia es bastante trivial en términos de implementación en el compilador.

10

Tricky - tendrá que analizar el código C para esto. ¿Qué tan cerca debe estar el resultado? Ejemplo de lo que quiero decir:

int a, /* foo */ 
    b, /* << the unused one */ 
    c; /* bar */ 

Ahora, es obvio para los seres humanos que el segundo comentario tiene que ir.

Una pequeña variación:

void test(/* in */ int a, /* unused */ int b, /* out */ int* c); 

Una vez más, el segundo comentario tiene que ir, el anterior b este tiempo.

En general, quiere analizar su entrada, filtrarla y emitir todo lo que no sea la declaración de una variable no utilizada. Su analizador debería conservar los comentarios y las declaraciones #include, pero si no # incluye encabezados puede ser imposible reconocer las declaraciones (más aún si se usan macros para ocultar la declaración).Después de todo, necesitas encabezados para decidir si A * B(); es una declaración de función (cuando A es un tipo) o una multiplicación (cuando A es una variable)


[editar] Además:

Incluso si usted sabe que una variable no se utiliza, la forma correcta quitarlo depende mucho del contexto remoto. Por ejemplo, suponga

int foo(int a, int b, int c) { return a + b; } 

Claramente, no se utiliza. ¿Puedes cambiarlo a?

int foo(int a, int b) { return a + b; } 

Tal vez, pero no si se almacena & foo int a int(*)(int,int,int). Y eso puede suceder en otro lugar. Si (y solo si) eso sucede, debe cambiarlo a

int foo(int a, int b, int /*unused*/) { return a + b; } 
+0

¿No está haciendo la suposición (posiblemente) errónea de que los comentarios son correctos? –

+0

La pregunta estableció que la lista de variables no utilizadas estaba disponible externamente. Eso es bastante realista, los compiladores pueden encontrarlos. Mi punto aquí es que todavía necesita limpiar los comentarios asociados. – MSalters

+0

Parece que eres la única persona que intenta responder la pregunta real. Upvoted. – Constantin

5

¿Por qué desea hacer esto? Suponiendo que tiene un compilador de optimización decente (GCC, Visual Studio et al), la salida binaria no será diferente si elimina el 'int c' en su ejemplo original o no.

Si esto se trata sólo de limpieza del código, cualquier IDE reciente le dará una rápida conexión con el código fuente de cada advertencia, basta con hacer clic y borrar :)

+0

¡Deja un código bastante ilegible si tienes muchas variables sin usar! Tener una buena manera de resaltar las variables no utilizadas, así como las importaciones no utilizadas puede ser una herramienta muy útil en términos de limpieza de código. –

5

Mi respuesta es más de un comentario elaborada a MSalters' muy respuesta completa Iría más allá de lo "complicado" y diría que una herramienta de este tipo es imposible y desaconsejable.

Si usted está buscando simplemente eliminar las referencias a la variable, entonces usted podría escribir un analizador de código de su propia, pero habría que distinguir entre el contexto función es de tal

int foo(double a, double b) 
{ 
    b = 10.0; 
    return (int) b; 
} 

int bar(double a, double b) 
{ 
    a = 5.00; 
    return (int) a; 
} 

Cualquier analizador simple tendría problemas con 'a' y 'b' como variables no utilizadas.

En segundo lugar, si considera los comentarios como MSalter, descubrirá que las personas no hacen comentarios consistentes;

double a; 
/*a is designed as a dummy variable*/ 
double b; 

/*a is designed as a dummy variable*/ 
double a; 
double b; 

double a; /*a is designed as a dummy variable*/ 
double b; 

etc.

Así que la simple eliminación de las variables utilizadas creará comentarios huérfanos, que son sin duda más peligroso que not commenting at all.

En última instancia, es una tarea obscenamente difícil de hacer con elegancia, y sin embargo, estarías modificando el código. Al automatizar el proceso, empeoraría el código.

Por último, debe considerar por qué las variables estaban en el código en primer lugar, y si están en desuso, por qué no se eliminaron cuando estaban todas sus referencias.

0

Necesitará un buen analizador que preserve la posición original del carácter de los tokens (¡incluso en presencia del preprocesador!). Existen algunas herramientas para la refacturación automatizada de C/C++, pero están lejos de la corriente principal.

Te recomiendo que visites Taras' Blog. El tipo está haciendo grandes refactorizaciones automatizadas de la base de código de Mozilla, como reemplazar parámetros externos por valores devueltos.Su principal herramienta para la reescritura de código es Pork:

El cerdo es un análisis ++ C y volver a escribir cadena de herramientas. El núcleo de Pork es un analizador C++ que proporciona las posiciones de caracteres exactos para el inicio y el final de cada nodo AST, así como el conjunto de expansiones macro que contienen cualquier ubicación . Esta información permite que C++ se reescriba automáticamente en una forma precisa .

Desde el blog:

cerdo Hasta ahora se ha utilizado para “menores” cosas como cambiar el nombre de clases & funciones, girando outparameters y corregir errores prbool . Además, Pork demostró ser en un experimento que implicó reescribir casi todas las funciones (es decir, generando un parche de 3 + MB) en Mozilla al utilizar la recolección de basura en lugar del recuento de referencias .

Es para C++, pero puede satisfacer sus necesidades.

0

Uno de los carteles de arriba dice "imposible e inconveniente". Otro dice "complicado", que es la respuesta correcta. Necesita 1) un analizador completo C (o cualquier idioma de interés), 2) procedimientos de inferencia que entienden el lenguaje referencias de identificador y flujos de datos para determinar que una variable está realmente "muerta", y 3) la capacidad de de hecho modifique el código fuente.

Lo difícil de todo esto es la enorme energía para construir 1) 2) 3). No se puede justificar para ninguna tarea de limpieza individual. Lo que se puede hacer es construir dicha infraestructura específicamente con el objetivo de amortizarla en muchas tareas diferentes de análisis y transformación de programas .

Mi empresa ofrece una herramienta tal: la reingeniería de software DMS Toolkit. Consulte http://www.semdesigns.com/Products/DMS/DMSToolkit.html DMS tiene interfaces de calidad de producción para muchos idiomas, incluyendo C, C++, Java y COBOL.

Hemos hecho construido un sistema automatizado de "encontrar declaraciones inútiles" herramienta para Java que hace dos cosas: a) a todas las listas (produciendo así la lista) b) hace una copia del código con el inútil declaraciones eliminado. Elija la respuesta que desea conservar :-)

Hacer lo mismo para C no sería difícil. Ya tenemos con una herramienta que identifica tales variables/funciones muertas.

Uno de los casos que no addess, es el "parámetro inútil" caso, robaba para eliminar un parámetro inútil, usted tiene para encontrar todas las llamadas de otros módulos, verificar que la configuración del argumento doesn' t tiene un efecto de lado y arranca el argumento inútil. Nosotros, de hecho, tenemos gráficos completos de todo el sistema de software de interés, y por lo que también sería posible .

Por lo tanto, es sólo difícil, y ni siquiera muy complicado si tiene la infraestructura adecuada.

-1

puede resolver el problema como un problema de procesamiento de texto. Debe haber un pequeño número de patrones de expresiones regulares como las variables locales no utilizadas se definen en el código fuente.

Usando una lista de los nombres de las variables utilizadas y los números de línea en el que se encuentre, puede procesar la línea por línea de código fuente en C. En cada línea puede iterar sobre los nombres de las variables. En cada nombre de variable Puede hacer coincidir los patrones uno a uno. Después de una coincidencia exitosa, conoce la sintaxis de la definición, por lo que sabe cómo eliminar la variable no utilizada de ella.

Por ejemplo, si la línea de fuente es: "int a, sin uso, b;" y el compilador informó "no utilizado" como una variable no utilizada en esa línea, que el patrón "/, sin usar, /" coincidirá y puede reemplazar esa subcadena con un solo ",".

Cuestiones relacionadas