language-agnostic warnings

language agnostic - ¿Es una buena idea eliminar las advertencias del compilador?



language-agnostic warnings (14)

¿Vale la pena el tiempo de un programador? ¿Será realmente un proyecto mucho mejor si rastreas cada advertencia del compilador?

Sí. Incluso los triviales sobre la falta de coincidencia de los signos pueden tener un profundo impacto en la generación y optimización de códigos.

En el pasado he trabajado con -Wall y otros switches para gcc para eliminar todas las advertencias del compilador para los proyectos en los que he estado involucrado. Del mismo modo, en Perl, siempre programo con uso estricto y uso advertencias (y a menudo -T también ) para tratar de lograr la mejor calidad de código que pueda. Entiendo que hace unos años, el grupo de porteros de Perl trabajó duro para hacer que Perl (el intérprete de Perl) compilara limpiamente bajo gcc con todas las advertencias habilitadas. Obviamente, sentían que era una buena idea para la calidad del código. También entiendo que hoy en día los programadores de Perl han agregado aún más advertencias a su código con Perl :: Critic, que les advierte cuando violan las mejores prácticas que se encuentran en el libro Perl Best Practices de Damian Conway (y de otras fuentes, creo).

Siempre tuve un buen presentimiento sobre el código que había limpiado de esta manera, pero a veces no podía evitar la sensación de que parte del trabajo había sido un poco desperdiciado. Por ejemplo, en mis clases de intro C hace más de una década, me enseñaron a comenzar mi función main () de la siguiente manera:

void main(void) {

Esto era mínimo y solo se podía usar cuando no devolvía un valor y no estaba accediendo a sus argumentos. Funciona muy bien en ese caso, pero las advertencias de gcc te permiten saber que esta función realmente debería verse así:

int main(int args, char* argv) {

Debo haber tipeado un par de cientos de líneas internas no utilizadas, líneas de caracteres anteriores en el día. ¿Realmente mejoré mi código, o simplemente usé mis dedos más cortos?

Actualmente estoy programando en Java en Eclipse, y nuestro proyecto tiene decenas de miles de advertencias. Me gustaría limpiarlos. Algunos de ellos son especialmente difíciles de entender y eliminar, pero poco a poco estoy aprendiendo. He tenido que manejar algunos de estos con las directivas del compilador para suprimir las advertencias (por lo general, en pequeños métodos mínimos para descartar la mala práctica de ignorar las advertencias), pero también estoy encontrando maneras de manejarlas.

¿Vale la pena el tiempo de un programador? ¿Será realmente un proyecto mucho mejor si rastreas cada advertencia del compilador?

Si nada más, parece que sería bueno reducir el número de advertencias a cero para que las advertencias serias no se pierdan en el desastre.

Nota : Duplicado de esta pregunta


Eclipse, IntelliJ y otros sistemas modernos de calidad de código tienen un gran número de advertencias disponibles.

Limpiar las advertencias es una práctica útil, aunque solo sea para calmar el ruido. Su código probablemente ya tiene algunos de estos que son errores reales.

Sin embargo, muchas de las advertencias son probablemente falsas. Algunas advertencias de Eclipse son cosas como micro-optimizaciones o detalles estilísticos. Esto significa que algunas de sus limpiezas deben modificar la configuración de su herramienta, en lugar de cambios de código o directivas de supresión localizadas.


Estoy de acuerdo con todas las respuestas que dicen "corrígelas todas", pero me gustaría presentar una opinión contraria:

Existen sistemas heredados donde algunos (muchos o todos) componentes no tienen un mantenedor dedicado y grandes partes del sistema son básicamente desconocidas. Reparar las advertencias del compilador en un código desconocido puede tomar una cantidad considerable de código (ya que para cada advertencia el código junto con su contexto debe ser entendido) e introduce una posible fuente de errores (algunos códigos dependen del comportamiento indefinido). Y dado que tales sistemas legacy rara vez tienen una amplia cobertura de prueba, ni siquiera puede confiar en las pruebas para notificarle las regresiones.


Hay dos prototipos compatibles para main en C.

int main(void)

y

int main(int argc, char **argv)

void main(void) no es técnicamente correcto, aunque puede ser compatible con algunos compiladores como una extensión del estándar.

Entonces, en su caso particular, puede usar una declaración breve de main y, si es compatible, no activará la advertencia.


Le ahorrará al compilador el tiempo de escribir las advertencias, y le facilitará la búsqueda de advertencias potencialmente peligrosas si reduce el número de advertencias frívolas en su código. ¿Vale la pena el tiempo que lleva cazar cada advertencia y arreglarlo? Por lo general, no ... pero vale la pena corregir las advertencias cuando son obvias y fáciles de corregir, o cuando necesita tomarse el tiempo y cambiar la lógica que contiene las advertencias por otra razón.


Me voy a mover contra el paquete aquí y decir que puede haber algunas advertencias de compilación que no valen la pena corregir. El siguiente ejemplo:

Tenemos una gran cantidad de código escrito antes de Java 1.5 y genéricos. Aún funciona. Eclipse también genera literalmente miles de advertencias sobre colecciones sin parametrizar. Prácticamente todas estas colecciones tienen un alcance limitado; ellos nunca van a romperse Pero espera, puedes preguntar; ¿qué pasa con las pocas colecciones que no están limitadas en su alcance? ¿No estás arriesgando una colección en algún lugar que contenga una instancia de algo que nunca debería ir allí?

La respuesta es: una gran parte de ese código tampoco se modifica. Es legado-ish; ningún código nuevo está modificando esas colecciones, y ese código se ha utilizado durante años sin problemas. Todavía está en nuestra base de código, y tendríamos que mantenerlo si se manifiesta un error, pero en la práctica, ha hecho su trabajo. Pasar el tiempo necesario para parametrizar todas esas colecciones genéricas tomaría tiempo de otros proyectos necesarios.

Tenga en cuenta las advertencias aquí, entonces:

  • El código se ha utilizado durante mucho tiempo sin informar errores.
  • El código no está sufriendo ninguna edición sustancial.

Si alguno de estos deja de ser cierto, por ejemplo, un error se manifiesta de repente, y tenemos que entrar y editar, las advertencias de repente se vuelven más valiosas para solucionar. (Por cierto, también son muy económicos de corregir en este punto, podemos arreglar los bloques relevantes en el camino mientras solucionamos el error).


Mi opinión. Sí.

Como dijiste al final. Ayuda a resaltar los errores reales.

Cuando ejecuta un script Perl cgi que genera advertencias en un servidor Apache, las advertencias se registran en error.log. Por qué perder el espacio Arregla las advertencias

También creo que es una experiencia de aprendizaje para comprender mejor el lenguaje y el compilador. No me di cuenta de que el alcance dinámico era incluso una característica de Perl hasta que comencé a usar strict.


Otra razón para asegurarse de que su código compila sin advertencias es que, si alguien más * tiene que hacer cambios en el código en algún momento en el futuro, un buen lugar para comenzar es asegurarse de que puedan compilar el código en su estado actual. formar.

Sin embargo, si lo hacen y ven muchas advertencias, ¿estas advertencias siempre han existido o han instalado el compilador incorrectamente en su PC?

Al menos si hay una regla (y un recuadro para marcar en la lista de verificación, si usa una) que el código debe compilar sin advertencias, entonces evita esta ambigüedad.

(* Alguien más puede incluir su yo futuro).


Sí definitivamente. Una advertencia es una indicación de que algo puede estar mal en su código. Ya sea que lo arregles, o deberías desactivar la advertencia: si no vas a actuar en consecuencia, tener la advertencia solo te impide detectar cuándo aparecen nuevas advertencias.

La forma más sencilla de obtener y mantener el código libre de advertencias es compilar siempre con -Werror (/ WX en Visual Studio) o equivalente.


Sí. Hasta los triviales valen la pena arreglarlos. Este es el por qué. Algunos, como el ejemplo de main que mencionas, probablemente no valen la pena por sí mismos, pero están en conjunto. La mayoría de las advertencias del compilador le ahorrarán dolor directo a largo plazo. Son errores que esperan suceder (o que suceden ahora). Para encontrarlos, necesitas una forma fácil de detectarlos. Si arreglas todas las advertencias, cada nueva advertencia es una bandera roja y fácil de notar. Si arreglas todos los críticos, pero dejas solo algunos como el problema "principal", perderás los nuevos críticos.

¿Cuál es más fácil de recordar? ¿Que cualquier advertencia debe ser reparada o que tenía 23 advertencias irrelevantes en esta base de código ayer, y si ve 24 necesita ir a echar un vistazo?

En la base de código en la que trabajo, le decimos al compilador que genere errores en todas las advertencias. Esto nos obliga a arreglarlos y mantiene el código en una forma mucho mejor. Si alguna vez hay una advertencia que realmente no vale la pena corregir, siempre hay #pragma para hacerlo desaparecer. De esa manera todavía tienes una línea brillante para el fracaso.


Siempre debe intentar que no aparezcan advertencias en una compilación. De esta forma, nuevas advertencias llaman la atención. (Mi experiencia más frustrante con esto fue el compilador de AIX C ++ en 2002, que escupió cientos de advertencias por código que ni siquiera estaba fuertemente modelado).

Sepa qué significa cada advertencia. En su caso, debería haber tipeado el estándar int main() lugar del incorrectamente void main(void) o el int main(int argc, char **argv) torcido int main(int argc, char **argv) . Elimine lo que pueda y suprima las advertencias que haya considerado aceptables.

Es posible que no desee corregir cada advertencia. Como dice saua, existen sistemas heredados donde la fijación de advertencias es francamente peligrosa, y sistemas complejos como CGAL en los que tampoco se quiere ensuciar con el código. Al convertir nuestras aplicaciones en menos de 64 bits, encontré casos en los que podía eliminar una advertencia solo con un molde, lo que podría haber causado otros problemas. Suprimimos esa advertencia.



Su ejemplo es una ilustración perfecta de por qué las advertencias no deben ser ignoradas. void main(void) es un prototipo no válido (¡pero int main(void) funciona!)) y su código puede fallar en algunos compiladores. Tu compilador fue lo suficientemente bueno como para señalarlo.

Descubrí que casi todas las advertencias apuntaban a un problema real, incluso si no entendía la causa en ese momento. Básicamente, siempre hice algo y pretendí algo más. El efecto podría haberse logrado de todos modos, pero solo por pura coincidencia.

Trate las advertencias como errores. Existen excepciones (hay una en el compilador VB.NET sobre tipos de valores no inicializados) pero son extremadamente raras. Y si alguna vez tropieza con una de estas excepciones, lo sabrá .


Sí, hazlo ...

Ayer mismo lo hice para un proyecto en el trabajo. Al eliminar las advertencias surgieron dos problemas que resultaron ser errores reales.

Era un proyecto C, y en una fuente se llamó el sqrt (raíz cuadrada). Recibí la siguiente advertencia:

test.c:4: warning: implicit declaration of function ''sqrt''

Resultó que el codificador olvidó incluir el archivo de encabezado correcto y se llamó a la raíz cuadrada con argumentos enteros, no flotantes. Esto obviamente estaba mal y no era lo que pretendía.

La advertencia ha estado allí durante bastante tiempo, pero nadie lo ha visto porque se perdió en las otras 1000 advertencias inofensivas que simplemente se desplazaron por la pantalla. Las advertencias están ahí por una razón.

Por cierto, arreglar las advertencias me llevó como ... 4 horas ... Eso no es nada comparado con el tiempo que tomó escribir todo eso.