Programadores novatos frustrados por la falta de un glosario de errores del compilador

66

Un amigo de mi familia me pidió un poco de ayuda mientras aprende a programar (en el lenguaje C). Mientras hablábamos, expresó su frustración por tener dificultades para comprender los mensajes de error que su compilador (GCC) le está dando cuando comete errores. No entiende todos los términos utilizados, y a veces es su combinación lo que está más allá de su comprensión. Me preguntaba "¿Cómo es que la documentación del compilador no incluye explicaciones más largas de los mensajes de error?" - Y no tenía una buena respuesta para él.

Yo mismo, como programador con más experiencia, rara vez me encuentro en esta situación, pero esos casos raros suceden: algún mensaje de error exótico que no había encontrado antes. Me las arreglo para buscar el mensaje de error en un motor de búsqueda, pero aparentemente eso no siempre funciona para él, especialmente porque los errores con los que se encuentra son más comunes y ocurren en múltiples casos distintos, que tiene problemas relacionados con su propio.

Entonces, ¿cómo debe un programador novato abordar el desafío de comprender los mensajes de error del compilador? Específicamente, con la combinación de C y GCC?

einpoklum - reinstalar a Monica
fuente
77
"Entonces, ¿cómo debe un programador novato abordar el desafío de comprender los mensajes de error del compilador?" / sarcasmo La primera habilidad necesaria es poder leer cada bit del mensaje del compilador, incluso relacionarlo con el contexto mismo. / sarcasmo apagado. Raramente resulta ser una falla o un error en el compilador.
πάντα ῥεῖ
10
@MasonWheeler: un novato a menudo no elige qué compilador usar cuando se está entrenando. Y GCC es un denominador común de muchos, muchos sistemas ...
einpoklum - reincorporar Monica
24
Cuando se trata de errores de plantilla GCC C ++, encuentro que si dejo de leer después de "Error <file: line>" y estudio los archivos fuente, encuentro el error más rápido, con un efecto secundario adicional de mantener mi cordura, que si leí el error real dado por GCC .....
mattnz
18
La solución es obvia: utilice un compilador con resultados menos confusos. Sugiero rmcc . Se imprime Yes.o No.depende de si su código se compiló o no. ¡Al instante elimina la frustración de no entender mensajes largos e inútiles!
tubería
21
C no es un buen lenguaje para principiantes, y te has topado con uno de los motivos. Dicho esto, Clang tiende a ofrecer errores mucho mejores que también podrían ser más atractivos para los principiantes.
Theodoros Chatzigiannakis

Respuestas:

164

Algunas técnicas útiles:

  • Enciende -Wally -Werror. Puede parecer contradictorio cuando tiene dificultades para descifrar mensajes de error para crear aún más mensajes de error, pero las advertencias suelen ser más fáciles de entender y más cercanas a la fuente real del problema, e ignorarlas puede conducir a errores que son difíciles de entender. .
  • Solo intenta corregir el primer error de la lista. A menudo, los errores se combinan entre sí, lo que lleva a mensajes de error posteriores que en realidad no son errores reales. Arregle uno y recompile. Mejorará la corrección de múltiples mensajes de error cuando gane más experiencia.
  • Use la versión más nueva posible del compilador. C es un lenguaje extremadamente estable. Por lo tanto, una gran parte de las mejoras en los compiladores más nuevos no es agregar funciones de lenguaje, sino mejorar la experiencia del desarrollador, incluidos mejores mensajes de error. Muchas distribuciones de Linux ampliamente utilizadas tienen versiones muy antiguas de gcc por defecto.
  • Programa incrementalmente. No intentes escribir una tonelada de código antes de compilar. Escriba la menor cantidad posible que aún se compilará. Si solo ha cambiado una línea desde la última vez que se compiló limpiamente, es mucho más fácil descubrir qué línea contiene el problema real.
  • Escribir pruebas unitarias. Le da más confianza para hacer cambios de refactorización clarificadores al corregir errores de compilación.
Karl Bielefeldt
fuente
23
Un buen IDE también puede ayudar en gran medida la experiencia, por ejemplo. subrayando errores en rojo.
BlueRaja - Danny Pflughoeft
86
"Programe de forma incremental. No intente escribir una tonelada de código antes de compilar. Escriba la menor cantidad posible que aún se compilará. Si solo ha cambiado una línea desde la última vez que se compiló limpiamente, es mucho más fácil de entender qué línea contiene el problema real ". Esto, tanto esto. Además, la mayoría de los IDE le avisarán si escribe código que no se compilará y resaltarán los errores.
Polygnome
44
@einpoklum: no subestimes la tercera opción; Los mensajes de error del compilador han mejorado mucho. En una línea similar, use varios compiladores (por ejemplo, gcc y clang): detecta más errores / advertencias y uno de ellos podría tener un mejor diagnóstico para un problema específico que el otro.
Mat
19
@einpoklum: escribir cosas de forma más incremental es muy acertado , especialmente para principiantes. Diablos, si crees que las "tareas de programación cortas" no se pueden hacer de forma incremental, dividiéndolas en varias funciones pequeñas e implementando y compilando una por una, deberías tratar de mejorar esa habilidad por ti mismo ...
Doc Brown
44
Un truco que me ayudó: si el mensaje de error menciona la Línea N, marque la Línea N-1. Por ejemplo, si le falta un punto y coma en la línea 17, el mensaje de error dirá que algo está mal con la línea 18. Esto se debe a que el compilador esperaba un punto y coma, pero en su lugar obtuvo otra cosa en la siguiente línea.
user2023861
56

Tu amigo no necesita un glosario. Un glosario no lo ayudará. Lo que necesita es una mejor intuición sobre qué hacer cuando se producen errores de compilación.

Los errores del compilador de C no son tan intuitivos como, por ejemplo, los errores del compilador de C #, debido a muchas razones que tienen que ver principalmente con la naturaleza "cercana al metal" de C. Resolver los errores del compilador en C no es un ejercicio de coincidencia de patrones, porque el error Puede que recibir no tenga nada que ver con el problema real. A diferencia de C # o Java, donde un mensaje de error generalmente se asigna a una ubicación y problema de código preciso, es probable que los errores en C sean numerosos y lejanos.

Un ejemplo de esto es "punto y coma esperado" o cualquier número de errores de sintaxis que indican que el analizador se colgó en algo (no necesariamente un punto y coma). O algo así como "declaración de reenvío inesperada", un error que, cuando lo veo, significa invariablemente que me equivoqué de mayúsculas en uno de mis archivos .h, pero que no apunta al archivo .h como la fuente del problema.

La estrategia de tu amigo no debería ser un patrón que coincida con una lista de errores y soluciones; debería ser entender la sintaxis y la especificación del lenguaje C lo suficientemente bien como para descubrir cuál es el problema real .

Robert Harvey
fuente
17
No. La idea es conocer el idioma lo suficientemente bien como para saber que no se puede asignar una expresión numérica, sino solo una variable. No tiene que saber qué es un valor en absoluto, por lo que no lo enseñan en los cursos para principiantes.
Robert Harvey
18
Básicamente sí. Pero prácticamente, eso no es posible. He estado haciendo esto durante mucho tiempo y todavía recibo mensajes oscuros de error del compilador cada vez que escribo un programa en C. Sin embargo, rara vez me molesto en leer esos mensajes e intento entenderlos; en cambio, miro hacia dónde apunta el mensaje de error y, como sé cómo se supone que debe ser la estructura de sintaxis básica de un programa en C, puedo detectar el problema relativamente rápido sin perder tiempo descifrando mensajes de error.
Robert Harvey
36
En otras palabras, pedir un glosario para comprender los errores del compilador es como leer el diccionario para entender el idioma inglés; así no es exactamente cómo funciona. Aprendes y entiendes inglés al leerlo y escribirlo, no al leer el diccionario.
Robert Harvey
14
[encogimiento de hombros] Si no está utilizando un diccionario para simplemente complementar su conocimiento ya existente de inglés, sugeriría que lo está haciendo mal. Lo último que sugeriría es cualquier cosa que haga que los programadores novatos se obsesionen con el vocabulario más de lo que ya están. Los programadores no necesitan más palabras; Necesitan más habilidad.
Robert Harvey
13
@einpoklum, un glosario no va a ayudar aquí. Es probable que la descripción de la palabra 'lvalue' sea demasiado técnica para un principiante o en la línea de 'lo que puede estar en el lado izquierdo de una tarea' que es igualmente inútil.
Bart van Ingen Schenau
26

Una técnica relevante que vale la pena mencionar es usar un segundo compilador. Clang ha invertido en mejores mensajes de error, por ejemplo, pero cualquier forma alternativa de expresar el error puede ser esclarecedor.

Esto es especialmente cierto para el tipo más complejo de errores. Por ejemplo, cuando combina dos construcciones similares (no inusual para principiantes), los compiladores generalmente tienen un problema al generar el mensaje de error correcto. Esto puede causar confusión cuando el compilador da un mensaje de error sobre el uso incorrecto de la construcción A cuando realmente pretendía la construcción B. Un segundo compilador podría inferir que tenía la intención de B.

MSalters
fuente
13

Alguien intentó un glosario de errores de GCC en Wikilibros hace un tiempo, pero parece que nunca despegó y no se ha actualizado.

La sección "Errores" está mucho más avanzada que la sección "Advertencias". Parece que estaba dirigido a G ++, pero todavía es probable que haya información útil para su amigo allí.

nBurn
fuente
12

Además de las respuestas anteriores, tenga en cuenta que la mayoría de los compiladores no tienen glosarios integrales de errores; esto sería mucho trabajo para mantener, ya que los mensajes en sí mismos a menudo cambian, y hay muchos de ellos.

El mejor sustituto de un glosario es el acceso a internet. Siempre que el compilador produzca un error que no comprenda, tenga la seguridad de que es muy poco probable que sea el primero en haberlo encontrado y confundido. Un mensaje rápido de Google del mensaje exacto a menudo es suficiente para brindarle mucha información en un formato fácil de leer, a menudo con un código de ejemplo muy similar al suyo.

Más allá de eso, todo lo que necesita es tiempo y familiaridad con el lenguaje y el compilador. Eso, y el buen consejo dado por Karl Bielefeldt .

Dúthomhas
fuente
1
No creo que sea mucho trabajo mantener. Además, el público puede agregarlo, como Stackoverflow o un Wiki, y las personas de confianza tienen permisos de editor.
einpoklum - reinstalar a Monica
66
@einpoklum ¿Alguna vez has visto los documentos PHP? Eso es lo que sucede cuando dejas que la comunidad se encargue de esas cosas.
Kevin
44
Érase una vez, los manuales publicados (impresos) eran el único recurso disponible. Por lo general, estaban lo suficientemente bien escritos para proporcionar la información / orientación necesaria para resolver un problema. Con la evolución de Internet, ya nadie publica en forma impresa (si es que está en línea). La calidad del material de referencia "oficial" (en línea o no) ha disminuido considerablemente durante las décadas que he estado programando, por lo que el mejor recurso disponible es a menudo Google, y los resultados más útiles a menudo aparecen en Stackoverflow.
Zenilogix
2
Incluso si un glosario no existe, los motores de búsqueda pueden ser la mejor manera de acceder a ellos. También son útiles para detectar cuando estás en un territorio desconocido: cuando el único resultado de búsqueda es el código fuente que define el mensaje de error;)
Warbo
2
En la universidad, una vez recibí el error del compilador "Dave no cree que esto deba suceder. Envíele un correo electrónico a <[email protected]>". Le envié un correo electrónico y, de hecho, ¡fui el primero en detectar ese error en particular!
user1118321
6

El estándar C utiliza varios términos como "lvalue" y "object" en formas que son diferentes de otros lenguajes de programación, y los mensajes del compilador a menudo se escriben en dichos términos. El uso de la terminología es inconsistente en algunas partes de la Norma, pero cualquiera que desee aprender C debe mirar los borradores de las normas C89, C99 y / o C11, así como los documentos de justificación para ellos. La búsqueda de, por ejemplo, "borrador C99" o "justificación C89" debería funcionar bastante bien, aunque es posible que deba asegurarse de obtener el documento que espera. Aunque la mayoría de los compiladores admiten el estándar C99, puede ser útil saber cómo difiere del estándar C89, y la justificación del C89 puede ofrecer algunos antecedentes históricos que las versiones posteriores no ofrecen.

Super gato
fuente
11
El estándar C es un texto muy denso y pesado. Un principiante no tiene posibilidades de entenderlo.
NieDzejkob
44
@NieDzejkob: La terminología utilizada por los compiladores, que parece ser de lo que se trata la pregunta, se deriva del Estándar. Si bien tiene razón, algunas partes de la Norma son incomprensibles (en parte porque está diseñada por un comité, y los autores no parecen tener una comprensión constante de lo que se supone que significan partes de ella), pero cualquiera que quiera entender qué términos como "lvalue" significan que deben saber de dónde provienen. Además, si uno quiere entender por qué algo así x=0x1e-xproduce un error, realmente no sé nada más que el Estándar ...
supercat
3
Estoy de acuerdo con @NieDzejkob: el estándar C no es el tipo de texto con el que quieres confrontar a un novato. Los novatos necesitan experiencias prácticas positivas rápidamente . Y necesitan aprender cosas nuevas una por una a medida que aparecen. Leer un estándar o una justificación lleva demasiado tiempo mientras sobrecarga completamente a un novato con información.
cmaster
2
@cmaster: Empecé con el C89 Standard hace mucho tiempo, y no estaba tan mal incluso en los días anteriores a los navegadores con una práctica función de "buscar texto". Admito que los estándares posteriores han empeorado cada vez más. Si bien nadie debería confiar en el Estándar como referencia única, es importante reconocer la divergencia entre la sabiduría popular sobre cómo se comportan los compiladores de microcomputadoras y las formas en que el Estándar permite que se comporten comportamientos de baja calidad, por lo que uno estará preparado si uno tiene lidiar con esto último.
supercat
3
@cmaster: En cualquier caso, alguien que esté programando C debe conocer el Estándar y saber cómo consultarlo cuando sea necesario, incluso si no van a tratar de leerlo todo. Si se realiza una búsqueda web de una función de biblioteca estándar, por ejemplo, se puede encontrar una referencia que describe el comportamiento de una implementación en algunos casos de esquina sin mencionar que, desde el punto de vista del Estándar, esos casos de esquina invocan Comportamiento indefinido y otras implementaciones podrían No funciona de la misma manera. Si uno busca en el Estándar, uno puede evitar ese problema.
supercat
5

Me sorprende que nadie haya dado la respuesta obvia y, sospecho, la más utilizada en la práctica: simplemente no lea los mensajes de error.

La gran mayoría del valor de la mayoría de los mensajes de error es simplemente que algo está mal en tal o cual línea. La mayoría de las veces solo miro el número de línea y voy a esa línea. Mi "lectura" del mensaje de error en ese punto es, por lo general, lo que sea que atrape mi atención al pasar, ni siquiera un vistazo. Si no está claro de inmediato qué está mal en o cerca de la línea, entonces leeré el mensaje. Este flujo de trabajo es aún mejor con un IDE o herramientas que resaltan los errores en el acto y cumplen automáticamente la sugerencia de Karl Bielefeldt de considerar solo pequeños cambios.

Por supuesto, los mensajes de error no siempre apuntan a la línea apropiada, pero a menudo tampoco apuntan a la causa raíz apropiada, por lo que incluso una comprensión completa del mensaje de error sería de ayuda limitada. No lleva mucho tiempo hacerse una idea de qué mensajes de error son más confiables para localizar la línea adecuada.

Por un lado, es probable que la mayoría de los errores que cometa un novato sean dolorosamente obvios para un programador experimentado sin que sea necesaria la ayuda del compilador. Por otro lado, es mucho menos probable que sean tan obvios para el novato (aunque muchos serán obvios, la mayoría de los errores son estúpidos). En este punto, estoy completamente de acuerdo con Robert Harvey, el principiante simplemente necesita familiarizarse con el idioma. No hay forma de evitar esto. Los errores del compilador que hacen referencia a conceptos desconocidos o que parecen sorprendentes deben considerarse como indicaciones para profundizar el conocimiento del idioma. De manera similar para los casos en que el compilador se queja pero no puede ver por qué el código está mal.

Nuevamente, estoy de acuerdo con Robert Harvey en que se necesita una mejor estrategia para utilizar los errores del compilador. He esbozado algunos aspectos arriba y la respuesta de Robert Harvey da otros aspectos. Ni siquiera está claro qué espera hacer su amigo con un "glosario" de este tipo, y es muy poco probable que ese "glosario" sea realmente útil para su amigo. Los mensajes del compilador ciertamente no son el lugar para una introducción a los conceptos del lenguaje 1 y un "glosario" no es el mejor lugar para ello. Incluso con una descripción lúcida de lo que significa el mensaje de error, no le dirá cómo solucionar el problema.

1 Algunos idiomas, como Elm y Dhall (y probablemente Racket), así como algunas implementaciones de idiomas "orientadas al principiante" intentan hacerlo. En este sentido, el consejo de MSalters para utilizar una implementación diferente es directamente relevante. Personalmente, considero que esas cosas son poco convincentes y no están orientadas al problema correcto. Esto no quiere decir que no haya formas de hacer mejores mensajes de error, pero, para mí, tienden a girar en torno a aclarar las creencias del compilador y la base de esas creencias.

Derek Elkins
fuente
4

Entonces, ¿cómo debe un programador novato abordar el desafío de comprender los mensajes de error del compilador? Específicamente, con la combinación de C y GCC?

Dígale a su amigo que haga lo siguiente cuando encuentre un error que no entienda:

  • Elimine / comente el código agregado desde la última compilación exitosa.
  • Vuelva a colocar pequeñas partes y compile
  • Repita hasta que ocurra el error

Los errores del compilador solo le dicen lo que el compilador no entiende acerca de su código, no lo que está mal con él. Este enfoque lleva aproximadamente la misma cantidad de tiempo que Googlear el error y leer algunos documentos o una publicación de StackOverflow, pero brinda una comprensión mucho mejor de lo que está haciendo mal.

También haga que compilen con frecuencia hasta que comiencen a trabajar en proyectos que tardan minutos en crearse, detectar errores antes de agregar demasiado código ayuda mucho.

Finalmente, dígales que trabajen en una cosa a la vez, no trabajen en múltiples archivos sin compilar entre ellos, no introduzcan múltiples dependencias a la vez, etc.

Kevin
fuente
4

Otra técnica sería que el amigo escribiera su propio glosario con el tiempo a medida que encuentre diferentes mensajes de error. A menudo, la mejor manera de aprender algo es enseñarlo. Por supuesto, para cuando termine el glosario, probablemente ya no lo necesite.

Mi experiencia personal con GCC es que cada mensaje de error se relaciona con un conjunto "habitual" de errores. Por ejemplo, cuando GCC dice "¿olvidó el &", generalmente significa que olvidé los paréntesis. Por supuesto, qué errores corresponden a qué mensajes de error dependerán del programador, otra buena razón para que el amigo escriba su propio glosario.

Owen
fuente
1
Este documento tiene el beneficio secundario tremendamente importante de que se puede poner en línea (incluso si solo tiene 5-10 entradas) y sería un gran diferenciador al solicitar pasantías.
Josh Rumbut