Programmatore (i) principiante (i) frustrato dalla mancanza di un glossario di errori del compilatore


65

Un amico della mia famiglia mi ha chiesto un po 'di aiuto mentre impara a programmare (in linguaggio C). Mentre stavamo parlando, ha espresso frustrazione per avere difficoltà a capire i messaggi di errore che il suo compilatore (GCC) gli sta dando quando commette errori. Non capisce tutti i termini usati, e talvolta è la loro combinazione che va oltre la sua comprensione. Mi stava chiedendo "Come mai la documentazione del compilatore non include spiegazioni più lunghe dei messaggi di errore?" - e non avevo una buona risposta per lui.

Io stesso - come programmatore più esperto - mi trovo molto raramente in questa situazione, ma accadono quei rari eventi - un messaggio di errore esotico che non avevo mai incontrato prima. Riesco a cavarmela cercando il messaggio di errore in un motore di ricerca, ma a quanto pare non sempre funziona per lui, soprattutto perché gli errori che incontra sono più comuni e si verificano in più casi distinti, che ha problemi relativi al suo proprio.

Quindi, come dovrebbe un programmatore principiante affrontare la sfida di comprendere i messaggi di errore del compilatore? In particolare, con la combinazione di C e GCC?


7
"Quindi, come dovrebbe un programmatore principiante affrontare la sfida di comprendere i messaggi di errore del compilatore?" / sarcasmo La prima abilità necessaria è quella di essere in grado di leggere ogni bit dal messaggio del compilatore, incluso di metterlo in relazione con il contesto stesso. / sarcasmo spento. Raramente risulta essere un difetto o un bug nel compilatore.
πάντα ῥεῖ

10
@MasonWheeler: un principiante spesso non sceglie quale compilatore utilizzare durante la formazione. E GCC è un comune denominatore di molti, molti sistemi ...
einpoklum - reintegrare Monica

25
Quando si tratta di errori del modello GCC C ++, trovo che smetto di leggere dopo "Errore <file: linea>" e studio i file di origine, trovo l'errore più veloce, con un effetto collaterale aggiunto di mantenere la sanità mentale, che se leggessi l'errore reale dato da GCC .....
mattnz,

19
La soluzione è ovvia: utilizzare un compilatore con output meno confuso. Suggerisco rmcc . Stampa Yes.o No.dipende dal fatto che il codice sia stato compilato o meno. Allontana istantaneamente la frustrazione dal non capire messaggi lunghi e inutili!
pipe

21
C non è una buona lingua per i principianti - e ti sei imbattuto in uno dei motivi. Detto questo, Clang tende a offrire errori molto migliori che potrebbero anche essere più interessanti per i principianti.
Theodoros Chatzigiannakis,

Risposte:


163

Alcune tecniche utili:

  • Accendi -Walle -Werror. Potrebbe sembrare controintuitivo quando si fatica a decifrare i messaggi di errore per creare ancora più messaggi di errore, ma gli avvisi sono in genere più facili da capire e più vicini alla fonte effettiva del problema e ignorarli può portare a errori che sono difficili da capire .
  • Prova solo a correggere il primo errore nell'elenco. Spesso gli errori si combinano a vicenda, portando a messaggi di errore successivi che non sono realmente errori reali. Risolvi uno e ricompila. Migliorerai nel correggere più messaggi di errore quando acquisirai più esperienza.
  • Utilizza la versione del compilatore più recente possibile. C è un linguaggio estremamente stabile. Pertanto, gran parte dei miglioramenti apportati ai compilatori più recenti non consiste nell'aggiungere funzionalità linguistiche, ma nel migliorare l'esperienza degli sviluppatori, compresi i migliori messaggi di errore. Molte distribuzioni Linux ampiamente utilizzate hanno versioni molto vecchie di gcc per impostazione predefinita.
  • Programma in modo incrementale. Non provare a scrivere una tonnellata di codice prima di compilare. Scrivi la quantità più breve possibile che verrà comunque compilata. Se hai modificato solo una riga dall'ultima volta che è stata compilata in modo pulito, è molto più facile capire quale riga contiene il problema reale.
  • Scrivi unit test. Ti rende più sicuro apportare chiarimenti alle modifiche del refactoring durante la correzione degli errori di compilazione.

23
Un buon IDE può anche aiutare notevolmente l'esperienza, ad es. sottolineando gli errori in rosso.
BlueRaja - Danny Pflughoeft,

86
"Programma in modo incrementale. Non provare a scrivere una tonnellata di codice prima della compilazione. Scrivi la quantità più breve possibile che verrà comunque compilata. Se hai modificato solo una riga dall'ultima volta che è stato compilato in modo pulito, è molto più facile da capire quale riga contiene il problema reale. " Questo, così tanto. Inoltre, la maggior parte degli IDE ti avviserà se scrivi codice che non verrà compilato ed evidenzierà gli errori.
Polygnome,

4
@einpoklum: non sottovalutare la terza opzione; i messaggi di errore del compilatore sono migliorati molto. Allo stesso modo, usa diversi compilatori (ad esempio gcc e clang): rileva più errori / avvisi e uno di essi potrebbe avere una diagnostica migliore per un problema specifico rispetto all'altro.
Mat,

19
@einpoklum: scrivere cose più incrementale è molto azzeccato, soprattutto per i principianti. Diamine, se ritieni che i "brevi incarichi di programmazione" non possano essere svolti in modo incrementale, suddividendoli in diverse piccole funzioni e implementandoli e compilarli uno per uno, dovresti cercare di migliorare tale abilità per te stesso.
Doc Brown,

4
Un trucco che mi ha aiutato: se il messaggio di errore menziona la riga N, controlla la riga N-1. Ad esempio, se ti manca un punto e virgola sulla riga 17, il messaggio di errore indicherà che qualcosa non va con la riga 18. Questo perché il compilatore si aspettava un punto e virgola, ma invece ha ottenuto qualcos'altro nella riga successiva.
user2023861

56

Il tuo amico non ha bisogno di un glossario. Un glossario non lo aiuterà. Ciò di cui ha bisogno è una migliore intuizione su cosa fare quando si verificano errori del compilatore.

Gli errori del compilatore C non sono così intuitivi come, diciamo, gli errori del compilatore C #, per molte ragioni principalmente legate alla natura "vicina al metallo" di C. La risoluzione degli errori del compilatore in C non è un esercizio di abbinamento dei modelli, perché l'errore ricevere potrebbe non avere nulla a che fare con il problema reale. A differenza di C # o Java, dove un messaggio di errore in genere si associa a una posizione e un problema di codice precisi, è probabile che gli errori in C siano numerosi e lontani.

Un esempio di questo è "punto e virgola previsto" o qualsiasi numero di errori di sintassi che indicano che il parser è stato bloccato su qualcosa (non necessariamente un punto e virgola). O qualcosa come "dichiarazione anticipata imprevista", un errore che, quando lo vedo, significa inevitabilmente che ho sbagliato le lettere maiuscole in uno dei miei file .h, ma che non indica il file .h come l'origine del problema.

La strategia del tuo amico non dovrebbe essere quella di abbinare questo a un elenco di errori e soluzioni; dovrebbe essere per capire la sintassi e le specifiche del linguaggio C abbastanza bene da capire qual è il problema reale .


17
No. L'idea è di conoscere abbastanza bene la lingua per sapere che non è possibile assegnare un compito a un'espressione numerica, ma solo a una variabile. Non devi sapere che cos'è un lvalue, motivo per cui non lo insegnano nei corsi per principianti.
Robert Harvey,

18
In sostanza sì. Ma praticamente non è possibile. Lo sto facendo da molto tempo e ricevo ancora oscuri messaggi di errore del compilatore ogni volta che scrivo un programma C. Raramente mi preoccupo di leggere quei messaggi e cerco comunque di capirli; invece, guardo dove punta il messaggio di errore e poiché so come dovrebbe essere la struttura di sintassi di base di un programma C, posso individuare il problema relativamente rapidamente senza perdere tempo a decifrare i messaggi di errore.
Robert Harvey,

36
In altre parole, chiedere un glossario per capire gli errori del compilatore è un po 'come leggere il dizionario per capire la lingua inglese; non è proprio come funziona. Impara e capisci l'inglese leggendolo e scrivendolo, non leggendo il dizionario.
Robert Harvey,

14
[scrollata di spalle] Se non stai usando un dizionario solo per integrare la tua conoscenza dell'inglese già esistente, suggerirei che stai sbagliando. L'ultima cosa che suggerirei è qualsiasi cosa che induca i programmatori inesperti a rimanere bloccati sul vocabolario più di quanto non lo siano già. I programmatori non hanno bisogno di più parole; hanno bisogno di più abilità.
Robert Harvey,

13
@einpoklum, un glossario non aiuterà qui. È probabile che la descrizione della parola "lvalue" sia troppo tecnica per un principiante o sulla falsariga di "ciò che può essere sul lato sinistro di un compito" che è altrettanto inutile.
Bart van Ingen Schenau,

26

Una tecnica pertinente degna di nota è l'utilizzo di un secondo compilatore. Clang ha investito in messaggi di errore migliori, ad esempio, ma qualsiasi modo alternativo per pronunciare l'errore può essere illuminante.

Questo è particolarmente vero per il tipo più complesso di errori. Ad esempio, quando si confondono due costrutti simili (non insoliti per i principianti), i compilatori hanno in genere un problema nella generazione del messaggio di errore corretto. Ciò può causare confusione quando il compilatore fornisce un messaggio di errore sull'utilizzo errato del costrutto A quando si intendeva effettivamente il costrutto B. Un secondo compilatore potrebbe dedurre che si intendesse B.


13

Qualcuno ha fatto un tentativo nel glossario degli errori GCC su Wikibooks qualche tempo fa, ma sembra che non sia mai decollato e non sia stato aggiornato.

La sezione "Errori" è molto più avanti della sezione "Avvertenze". Sembra che fosse indirizzato a G ++, ma è probabile che ci siano ancora alcune informazioni utili per il tuo amico.


12

Oltre alle risposte di cui sopra, tieni presente che la maggior parte dei compilatori non dispone di glossari di errori completi: sarebbe molto lavoro da mantenere poiché i messaggi stessi cambiano spesso e ce ne sono molti.

Il miglior sostituto per un glossario è l'accesso a Internet. Ogni volta che il compilatore produce un errore che non capisci, conforta che è altamente improbabile che tu sia il primo ad averlo incontrato ed essere stato confuso. Un rapido Google del messaggio esatto è spesso sufficiente per darti molte informazioni in un formato di facile lettura, spesso con un codice di esempio molto simile al tuo.

Oltre a ciò, tutto il tempo e la familiarità con la lingua e il compilatore sono tutto ciò di cui hai bisogno. Quello e il buon consiglio dato da Karl Bielefeldt .


1
Non credo che sarebbe un sacco di lavoro da mantenere. Inoltre, può essere aggiunto al pubblico, come StackOverflow o un Wiki, con persone fidate che hanno ottenuto i permessi dell'editor.
einpoklum - ripristina Monica

6
@einpoklum Hai mai visto i documenti PHP? Questo è ciò che accade quando lasci che la comunità si occupi di queste cose.
Kevin,

4
Una volta, i manuali (stampati) pubblicati erano l'unica risorsa disponibile. Di solito erano scritti abbastanza bene da fornire le informazioni / indicazioni necessarie per risolvere un problema. Con l'evoluzione di Internet, nessuno pubblica più in stampa (se non del tutto, è online). La qualità del materiale di riferimento "ufficiale" (online o altro) è notevolmente diminuita nel corso dei decenni che ho programmato, quindi la migliore risorsa disponibile è spesso Google, e i risultati più utili si presentano spesso in StackOverflow.
Zenilogix,

2
Anche se un glossario non esiste, i motori di ricerca possono essere il modo migliore per accedervi. Sono anche utili per individuare quando ti trovi in ​​un territorio inesplorato: quando l'unico risultato della ricerca è il codice sorgente che definisce il messaggio di errore;)
Warbo

2
Al college, una volta ho ricevuto l'errore del compilatore "Dave non pensa che ciò dovrebbe accadere. Ti preghiamo di inviargli un'e-mail a <dave@example.com>". Gli ho mandato un'e-mail e in effetti sono stato il primo ad aver riscontrato quel particolare errore!
user1118321

6

Lo standard C usa una serie di termini come "lvalue" e "object" in modi diversi dagli altri linguaggi di programmazione e i messaggi del compilatore sono spesso scritti in tali termini. L'uso della terminologia è incoerente in alcune parti dello standard, ma chiunque desideri imparare C dovrebbe esaminare le bozze degli standard C89, C99 e / o C11, nonché i documenti logici per essi. La ricerca, ad esempio, "bozza C99" o "logica C89" dovrebbe funzionare abbastanza bene, anche se potrebbe essere necessario assicurarsi di ottenere il documento che ci si aspetta. Sebbene la maggior parte dei compilatori supporti lo standard C99, può essere utile sapere in che modo differisce dallo standard C89 e la logica C89 può offrire un background storico che le versioni successive non lo fanno.


11
Lo standard C è un testo molto denso e pesante. Un principiante non ha alcuna possibilità di capirlo.
NieDzejkob,

4
@NieDzejkob: la terminologia utilizzata dai compilatori, che sembra essere la questione, deriva dallo standard. Mentre hai ragione sul fatto che alcune parti dello Standard sono incomprensibili (in parte perché è stato progettato dal comitato, e gli autori non sembrano avere una comprensione coerente di quali parti dovrebbero significare), ma chiunque voglia capire cosa termini come "lvalue" significa che devono essere consapevoli della loro provenienza. Inoltre, se si vuole capire perché qualcosa del genere x=0x1e-xproduce un errore, non so davvero altro che lo Standard ...
Supercat,

3
Sono d'accordo con @NieDzejkob: lo standard C non è il tipo di testo con cui vuoi confrontarti con un principiante. I neofiti hanno bisogno di esperienze pratiche positive veloci . E hanno bisogno di imparare cose nuove una per una mentre compaiono. Leggere uno standard o una logica richiede troppo tempo, sovraccaricando completamente un principiante con le informazioni.
cmaster

2
@cmaster: ho iniziato con lo standard C89 anni fa, e non era poi così male nemmeno nei giorni precedenti i browser con una pratica funzione "trova testo". Concederò che gli standard successivi sono sempre peggiorati. Mentre nessuno dovrebbe fare affidamento sullo Standard come unico riferimento, è importante riconoscere la divergenza tra la saggezza popolare su come si comportano i compilatori di microcomputer e i modi in cui lo Standard consente comportamenti di bassa qualità, quindi si sarà preparati se si ha trattare con quest'ultimo.
supercat,

3
@cmaster: In ogni caso, qualcuno che sta programmando C dovrebbe essere a conoscenza dello Standard e sapere come consultarlo quando necessario, anche se non proveranno a leggere il tutto. Se si esegue una ricerca Web per una funzione di libreria standard, ad esempio, è possibile trovare un riferimento che descriva il comportamento di un'implementazione in alcuni casi angolari senza menzionare che, dal punto di vista dello Standard, tali casi angolari invocano il comportamento indefinito e altre implementazioni potrebbero non funziona allo stesso modo. Se invece si cerca lo standard, si può evitare quel problema.
supercat,

5

Sono sorpreso che nessuno abbia dato la risposta ovvia e, sospetto, quello più spesso usato in pratica: semplicemente non leggere i messaggi di errore.

La stragrande maggioranza del valore della maggior parte dei messaggi di errore è semplicemente che qualcosa non va su tale e tale linea. Il più delle volte guardo solo il numero di riga e vado a quella riga. La mia "lettura" del messaggio di errore a quel punto di solito è esattamente ciò che il mio sguardo cattura di sfuggita, nemmeno una scrematura. Se non si capisce subito cosa c'è che non va nella linea o vicino, allora in realtà leggerò il messaggio. Questo flusso di lavoro è ancora migliore con un IDE o uno strumento che evidenzia errori sul posto e realizza automaticamente il suggerimento di Karl Bielefeldt di considerare solo piccoli cambiamenti.

Naturalmente, i messaggi di errore non puntano sempre alla riga appropriata, ma spesso non indicano nemmeno la causa principale appropriata, quindi anche una piena comprensione del messaggio di errore sarebbe di aiuto limitato. Non ci vuole molto per avere un'idea di quali messaggi di errore sono più affidabili nel trovare la linea corretta.

Da un lato, la maggior parte degli errori che un principiante potrebbe commettere sono probabilmente dolorosamente ovvi per un programmatore esperto senza che sia necessario l'aiuto del compilatore. D'altra parte, è molto meno probabile che siano così ovvi per il principiante (anche se molti saranno ovvi, la maggior parte degli errori sono errori stupidi). A questo punto sono completamente d'accordo con Robert Harvey, il novizio ha semplicemente bisogno di familiarizzare con la lingua. Non si può evitare questo. Gli errori del compilatore che fanno riferimento a concetti sconosciuti o sembrano sorprendenti dovrebbero essere visti come suggerimenti per approfondire la conoscenza della lingua. Allo stesso modo per i casi in cui il compilatore si lamenta ma non si vede perché il codice è errato.

Ancora una volta, concordo con Robert Harvey sulla necessità di una strategia migliore per l'utilizzo degli errori del compilatore. Ho delineato alcuni aspetti sopra e la risposta di Robert Harvey fornisce altri aspetti. Non è nemmeno chiaro cosa il tuo amico speri di fare con un "glossario" del genere, ed è molto improbabile che un simile "glossario" possa effettivamente essere di grande utilità per il tuo amico. I messaggi del compilatore non sono certamente il posto per un'introduzione ai concetti del linguaggio 1 e un "glossario" non è un posto molto migliore per esso. Anche con una descrizione lucida di cosa significa il messaggio di errore, non ti dirà come risolvere il problema.

1 Alcune lingue, come Elm e Dhall (e probabilmente Racket), così come alcune implementazioni di lingue "orientate ai principianti" tentano di farlo. In questo senso, il consiglio di MSalters di utilizzare un'implementazione diversa è direttamente pertinente. Personalmente trovo queste cose poco interessanti e non del tutto mirate al giusto problema. Questo non vuol dire che non ci sono modi per rendere migliori i messaggi di errore, ma, per me, tendono a girare intorno a rendere più chiare le credenze del compilatore e la base di quelle credenze.


4

Quindi, come dovrebbe un programmatore principiante affrontare la sfida di comprendere i messaggi di errore del compilatore? In particolare, con la combinazione di C e GCC?

Di 'al tuo amico di fare quanto segue quando incontra un errore che non capisce:

  • Rimuovi / commenta il codice aggiunto dall'ultima build riuscita.
  • Rimettine piccole parti e compilale
  • Ripetere fino a quando si verifica l'errore

Gli errori del compilatore indicano solo ciò che il compilatore non comprende sul codice e non ciò che non va. Questo approccio richiede all'incirca la stessa quantità di tempo in cui si cerca su Google l'errore e la lettura di alcuni documenti o un post StackOverflow, ma fornisce una comprensione molto migliore di ciò che si sta facendo di sbagliato.

Falli anche compilare spesso fino a quando non iniziano a lavorare su progetti che richiedono minuti per essere compilati, individuando gli errori prima di aggiungere troppo altro codice aiuta molto.

Infine, dì loro di lavorare su una cosa alla volta, non lavorare su più file senza compilare in mezzo, non introdurre più dipendenze contemporaneamente, ecc.


4

Un'altra tecnica sarebbe che l'amico scrivesse il proprio glossario nel tempo quando incontra diversi messaggi di errore. Spesso il modo migliore per imparare qualcosa è insegnarlo. Naturalmente, quando il glossario sarà finito, probabilmente non ne avrà più bisogno.

La mia esperienza personale con GCC è che ogni messaggio di errore si riferisce a una serie "abituale" di errori. Ad esempio, quando GCC dice "hai dimenticato il &", di solito significa che ho dimenticato le parentesi. Naturalmente, quali errori corrispondono a quali messaggi di errore dipenderanno dal programmatore, un'altra buona ragione per cui l'amico deve scrivere il proprio glossario.


1
Questo documento ha l'enorme vantaggio collaterale che potrebbe essere messo online (anche se ha solo 5-10 voci) e sarebbe un grande fattore di differenziazione quando si applica per gli stage.
Josh Rumbut,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.