Ciao e benvenuto.
In questa lezione vorrei parlare del debug.
Questo è un concetto molto importante che dovete comprendere nello specifico, dovete capire alcuni degli
strumenti e dei metodi che potete utilizzare per trovare e risolvere i bug.
Il debug è il processo di individuazione e correzione degli errori in un programma.
Di solito si tratta di errori logici.
Vi spiegherò la differenza tra errori di logica e di sintassi, ma può anche includere errori di sintassi
del compilatore.
È l'intero processo per gli errori di sintassi.
Il debug consiste nel capire cosa ci dice il compilatore.
È sempre meglio concentrarsi sulla risoluzione del primo problema rilevato.
Voglio passare in rassegna alcuni dei comuni errori e avvertimenti del compilatore,
ma una delle cose da sapere sempre sul compilatore è che esso può dare una serie
di errori.
È sempre meglio concentrarsi sul primo errore, perché questo primo errore può provocare altri errori.
Quindi può essere molto fuorviante vedere cinque errori in un programma che il compilatore vi sta dicendo che potrebbe avere un solo
errore e che il primo errore potrebbe essere la causa degli altri.
È quindi importante considerare sempre il primo errore in assoluto e risolverlo per primo.
In questo esempio molto semplicistico, abbiamo diversi errori nel codice.
Non abbiamo un.
Non abbiamo una parentesi sinistra iniziale, una parentesi graffa.
Non abbiamo il punto e virgola.
Restituiamo una stringa.
Quindi, quando salviamo questo file e andiamo a compilarlo e vediamo alcuni
errori rossi, quando andiamo a compilarlo, ci dice che abbiamo tre errori.
Non si vuole mai selezionare l'ultimo errore della riga sette, anche se in questo caso si tratta di un errore vero e proprio.
Si vuole sempre risolvere il primo errore.
Quindi si vede il primo errore elencato qui e si corregge il primo errore, quindi si ricompila e si esegue di nuovo.
Ma il motivo per cui è necessario farlo è solo per risolvere l'errore di primo livello, perché questo errore può causare altri
problemi.
Quindi, concentratevi sempre sulla correzione del primo errore Il debug e il processo di ricerca e correzione dei bug possono essere
molto complessi, dalla ricerca di semplici errori alla raccolta di grandi quantità di dati per l'analisi.
Tutto dipende.
A volte non si dispone di alcuna informazione, tranne la registrazione, e in questo caso è necessario
analizzare le cose.
A volte si verificano bug che non sono ripetibili.
Non è possibile riprodurlo perché si verifica in un'occasione così rara.
Di solito è quando si devono analizzare i registri o qualche variante di questo tipo.
La capacità di eseguire il debug da parte di un programmatore è un'abilità essenziale.
Si tratta di un'abilità di risoluzione dei problemi che può farvi risparmiare un'enorme quantità di tempo e denaro.
Quindi è un'abilità importante da imparare.
È un'abilità importante da sviluppare.
Ci vuole pratica.
Non è che si arriva da soli, non è che si arriva da soli.
Ci sono alcune tecniche e metodi che si possono applicare per migliorare
il debug.
Conosco un buon numero di sviluppatori che sono davvero bravi a scrivere codice per il software.
Capiscono molto bene il linguaggio, ma le loro capacità di debug sono molto scarse.
Può capitare che si presenti un bug e che la loro prima inclinazione a risolverlo sia davvero fuori strada.
E anche in questo caso, la pratica è fondamentale.
Diventerete sempre più bravi a eseguire il debug e a capire come trovare e risolvere i problemi, ma
è qualcosa che dovrete imparare anche voi.
La fase di manutenzione è la più costosa del ciclo di vita del software.
La fase di manutenzione è successiva al rilascio del prodotto e alla sua manutenzione.
Mantenere il sistema significa correggere tutti i bug che si presentano e aggiungere nuove funzionalità.
Così, ad esempio, quando Windows rilascia un nuovo sistema operativo come Windows 10, non ha finito di produrre
quel software.
Rimarrà sul campo per circa dieci anni.
È sempre responsabilità di Microsoft correggere eventuali nuovi bug o trovarne di nuovi per quel software.
Ed è per questo che vengono effettuati gli aggiornamenti automatici e si fanno cose del genere.
E poi noteranno anche che il sistema operativo presenterà nuove funzionalità in base ai cambiamenti del
mercato e della tecnologia.
La manutenzione è quindi molto importante.
Di conseguenza, trovare e correggere i bug è molto importante.
Tuttavia, è bene comprendere che i bug sono inevitabili.
Tutti i software hanno dei bug.
Nessuno può scrivere codice perfetto e non si tratta nemmeno necessariamente di scrivere codice perfetto.
È solo che le cose cambiano nel tempo.
Quindi anche questo potrebbe essere un problema.
Bisogna capire che il fatto che un software presenti dei bug non significa che sia un codice scritto male.
È inevitabile.
Quindi va bene avere dei bug, ma quando li trovate e li risolvete è ancora più bello perché vi sembra
di aver fatto qualcosa.
Problemi comuni.
E parleremo di problemi specifici legati alla visione.
Ma i problemi più comuni quando si cerca di eseguire il debug sono gli errori logici.
Gli errori di logica non hanno a che fare con il tipo opposto di errori di sintassi che il codice compila.
Funziona, ma non fa quello per cui è stato pensato.
Quindi c'è un qualche tipo di logica o di funzionalità prevista che non è corretta.
Forse avete un'istruzione IF e state saltando in quell'istruzione if nella condizione sbagliata.
Forse avete un ciclo che non viene eseguito il numero giusto di volte o non viene ordinato correttamente.
La funzionalità è interrotta, ma il compilatore dice: "Ehi, sembra tutto a posto".
Ecco un esempio di errore logico.
Un errore logico è quello in cui la sintassi è corretta, ma i risultati desiderati non sono corretti a causa di un qualche problema
logico.
In questo codice si vede che il ciclo for ha un punto e virgola alla fine, che è sintatticamente corretto.
Ma ci si aspetta che questo ciclo for venga eseguito cinque volte.
Ma non è così.
La durata della corsa sarà una sola.
Quindi, se diciamo build e costruiamo questo progetto, vediamo un avviso, il che è positivo e si dovrebbero sempre correggere tutti
gli avvisi.
Ma la compilazione è andata a buon fine.
Quando eseguiamo questo progetto, noterete che viene eseguito una sola volta e che stampa Hello
World una sola volta.
Questo è un esempio di errore logico.
Gli errori di sintassi sono direttamente collegati al compilatore.
Sono cose che non seguono le regole della lingua.
Non c'è il punto e virgola alla fine di un'affermazione.
Non hai un finale, giusto?
Parentesi con la sinistra, parentesi.
Manca una staffa.
Non state usando la parola chiave giusta, cose del genere.
Gli errori di sintassi sono solitamente causati dal compilatore Gli errori logici saranno causati dal programmatore
durante la fase di test.
Anche la corruzione della memoria è un problema comune, soprattutto in C.
Se non si libera la memoria dopo averla allocata correttamente, si
possono avere cose come riferimenti penzolanti e problemi di memoria legati alla memoria non utilizzata.
Si possono avere perdite di memoria.
Ecco un esempio di errore di memoria.
In questo particolare codice, abbiamo una perdita di memoria, quindi non abbiamo ancora parlato di puntatori.
Non abbiamo parlato dell'allocazione dinamica della memoria.
Ma in C è possibile allocare la memoria mentre il programma è in esecuzione.
È possibile utilizzare una funzione malloc.
Quindi stiamo marcando, allocando memoria, ma non la liberiamo mai.
Quindi possiamo costruire questo codice ed eseguirlo e tutto va bene, ma non stiamo liberando questo
errore.
Quindi, per correggere questo errore di memoria, dovremmo dire free e poi dire free
e X per liberare il puntatore.
Ma ogni volta che si alloca memoria, non la si libera.
È una perdita di memoria.
Un altro esempio potrebbe essere quello di non allocare la memoria, se creiamo un puntatore e poi cerchiamo
di assegnarlo, avremo una corruzione della memoria, perché la memoria non è stata allocata e stiamo
cercando di assegnarle un valore.
Questo è solo un piccolo esempio di memoria, corruzione, prestazioni e scalabilità.
Questo potrebbe essere un problema in cui la funzionalità è stata pensata così com'è e il codice è sintatticamente
corretto, ma non è molto efficiente o non si dispone dell'hardware per supportarlo.
Quindi, se si sta gestendo un server e non si dispone di hardware sufficiente per supportare tutte le richieste,
l'esecuzione sarà molto, molto lenta.
Oppure se avete scritto il vostro programma per funzionare con dieci utenti, ma quando ci sono molti
utenti, forse non è così veloce perché il database si impantana o altro.
Il codice funziona, ma non è stato progettato correttamente per gestire un numero elevato di utenti o qualsiasi
altro caso.
Mancanza di coesione.
Può trattarsi di un problema nel codice che riduce la qualità, legato al fatto che il codice sta facendo troppo o che una
funzione sta facendo troppo.
Non si tratta di un singolo focus o di un'applicazione che ha troppe funzionalità, che ha caratteristiche che non
vengono mai utilizzate e che quindi probabilmente richiederebbe una riprogettazione.
Ecco un esempio di programma non modulare, non coeso.
Avete una grande funzione che fa troppe cose, centinaia di righe di codice, migliaia di righe
di codice.
Si vuole suddividere una funzione in funzioni ausiliarie, moduli separati.
Questo rende il programma molto più coeso e facile da mantenere.
Quindi, invece di avere un grande metodo principale che esegue l'inizializzazione, la lettura dell'input, la ricerca di alcuni,
la ricerca della differenza, la ricerca del prodotto, la ricerca del quoziente, si può creare tutto questo codice e inserirlo
in moduli helper e separare il codice, in modo che la separazione possa aiutare a trovare e risolvere i bug molto più facilmente.
La coesione è sempre importante in C e di solito si risolve quando si ha un'alta coesione fornendo
metodi di aiuto.
Accoppiamento stretto.
Questo ha anche a che fare con la qualità del codice.
Qui ci sono molte dipendenze.
L'accoppiamento è diverso dalla coesione.
La coesione è il vostro unico obiettivo.
L'accoppiamento è quando si hanno dipendenze tra funzioni o tra oggetti.
Abbiamo parlato di accoppiamento, di variabili globali.
Se una variabile globale viene utilizzata in molte funzioni diverse, può causare dipendenze tra
queste funzioni.
Quindi, quando si scrive codice e si scrive codice di alta qualità, si vuole avere
una coesione molto alta e un accoppiamento molto basso.
Il processo di debug.
La prima cosa da fare prima di trovare e risolvere qualsiasi errore è capire il
problema.
Questo è riconducibile al fatto di non tuffarsi e iniziare a guardare il codice, ma di sedersi con il tester,
capire i requisiti, capire cosa sta succedendo.
Perché se non si capisce cosa sta succedendo, non si è nemmeno in grado di farlo.
Non si dovrebbe nemmeno tentare di risolverlo.
Una volta compreso il bug, cercate di riprodurlo perché la riproduzione del bug può aiutarvi a raccogliere ulteriori
informazioni.
Non è sempre possibile riprodurre i bug perché possono verificarsi in circostanze davvero rare.
Quindi, ad esempio, i bug che presentano condizioni di gara o addirittura corruzione della memoria possono verificarsi
solo in casi d'uso molto specifici e possono essere problemi intermittenti.
Ed è questo il caso?
E non si può riprodurre.
Diventerà sempre più difficile eseguire il debug.
Se si riesce a riprodurre il problema, di solito si possono raccogliere informazioni sufficienti per risolverlo.
La maggior parte dei problemi è risolvibile.
Inoltre, è possibile che non si riesca a riprodurre un problema in caso di ambiente multithread,
processi paralleli o problemi di threading.
Anche questi sono molto difficili da debuggare, ma sicuramente si cerca di riprodurli una volta che
si è capito qual è il problema in termini di comprensione del problema una volta che si è in grado di riprodurlo,
se non lo si è, allora si vuole cercare di applicare una sorta di divide et impera.
Si vuole cercare di isolare il bug, di semplificare il problema, perché la capacità di ridurre ci darà informazioni,
ma non necessariamente ci dirà in quale parte del codice si trova il bug.
Quindi, per cercare di semplificare il problema, si possono rimuovere alcune parti del caso di test originale, in modo
da non eseguire troppi test.
Si può isolare il problema ancora più in piccolo dicendo: "Oh, succede solo in questa situazione specifica".
È anche possibile commentare il codice.
Abbiamo parlato di funzioni che hanno solo stub e non hanno implementazioni.
A volte questo viene utilizzato nei test per limitare l'insieme dei problemi.
Inoltre, se si commenta il codice, si avrà meno codice in cui il bug può effettivamente verificarsi.
Quindi, mentre si commenta il codice o si eliminano le modifiche, il bug potrebbe scomparire e se il bug scompare, significa
che il codice che si è commentato potrebbe esserne la causa.
Quello che si vuole fare, però, è trasformare un programma di grandi dimensioni in tanti piccoli programmi,
tramite test o commenti.
Un'altra tecnica comune è quella di avere dei test unitari intorno al codice.
Se un test unitario fallisce, questo può dirvi esattamente dove potrebbe essere la logica o il problema nel vostro codice.
Una volta isolato il bug, si potrà trovare l'origine del problema nel codice, il codice specifico
che lo sta causando.
A volte è necessario utilizzare strumenti di debug, come ad esempio un debugger.
Parleremo di un debugger nello specifico, ma di solito, a seconda dell'IDE di sviluppo integrato che
si utilizza, ci sono debugger forniti con l'IDE.
Esistono anche debugger che possono funzionare in modo autonomo.
Il debugger più importante che utilizzeremo per la programmazione in C si chiama GDB.
Si tratta del debugger GNU, un simpatico strumento grafico che consente di interrompere l'esecuzione
del programma e di aggiungere punti di interruzione.
Poi, quando si interrompe l'esecuzione, è possibile esaminare riga per riga il codice e il valore delle variabili.
In questo modo è possibile vedere esattamente cosa succede nel codice mentre è in esecuzione.
È uno strumento prezioso.
È solo che è così utile.
Eseguiremo il debugger.
Vi mostrerò come aggiungere i punti di interruzione.
Vi mostrerò come impostare un orologio, in modo da poter osservare le variabili mentre cambiano, e come procedere
con il codice.
Dopo aver identificato l'origine del problema, bisogna risolverlo.
Questo richiede molta esperienza e pratica.
Solo perché avete trovato l'origine del problema, potreste non essere in grado di risolverlo solo sulla
base della vostra esperienza.
Questo a volte include la riprogettazione o il refactoring di altro codice che, soprattutto per problemi di scalabilità o di
prestazioni, potrebbe essere necessario riprogettare per consentire al software di essere più scalabile.
Quindi non è sempre facile individuare il problema e risolverlo.
Il problema a volte, specialmente i problemi più difficili come il threading o l'elaborazione parallela,
sono ancora più difficili da risolvere.
Ma man mano che si scrive sempre più codice, questo diventerà più facile da fare.
Infine, bisogna fare test a tappeto.
Testate sempre molti confini diversi.
Casi positivi, casi negativi e casi intermedi per verificare che il problema sia stato effettivamente risolto.
Alcune delle tecniche e degli strumenti disponibili.
Uno strumento comune e molto utilizzato è l'uso delle istruzioni di stampa.
È possibile utilizzare le istruzioni di stampa per tracciare il codice.
In C è possibile utilizzare l'istruzione print F e inserirla in più righe del codice per indicare il punto
in cui ci si trova.
Anche questo è utile, molto utile quando il programma si blocca.
Può aiutare a identificare il punto di arresto.
Quando si aggiungono queste dichiarazioni di stampa che tracciano il codice, si può aggiungere l'output nelle
dichiarazioni di stampa per vedere il valore delle variabili, perché il valore delle variabili può influenzare
lo stato e causare problemi logici.
Quindi l'aggiunta di istruzioni di stampa è molto, molto utile.
Può mostrare il flusso di esecuzione e aiutare a isolare l'errore.
I debugger, come ho menzionato in GDB, possono monitorare l'esecuzione del programma.
È possibile arrestarlo, eseguirlo riga per riga, riavviarlo, impostare punti di interruzione, osservare le variabili e la memoria.
Molto, molto utile quando si cerca di diagnosticare dove risiede un problema.
File di registro.
Anche i file di log sono molto utili, soprattutto per i bug che non possono essere ricreati.
È possibile analizzarli in un secondo momento per capire esattamente cosa stava succedendo quando si è verificato il bug.
Ciò significa che è necessario fornire buone dichiarazioni di log nel codice stesso, affinché
questo sia utile.
Si può quindi creare un proprio file di log e scriverlo durante l'esecuzione del programma, in modo che, in caso di errore,
si possano inviare i log agli sviluppatori.
In Xerox lo utilizziamo spesso perché quando riscontriamo dei problemi, non sempre riusciamo a riprodurli o possono
essere riscontrati sul campo.
Dobbiamo essere in grado di accedere a questi registri per vedere cosa stava succedendo quando si è verificato il bug.
Software di monitoraggio.
Esiste un software in grado di monitorare e analizzare in tempo reale l'utilizzo della memoria, il traffico di rete e le informazioni
sugli oggetti.
In questo modo si può capire se si sta allocando troppa memoria e non la si cancella.
Se disponete di uno strumento per l'utilizzo della memoria e del traffico di rete, che può dirvi se state
inviando troppi pacchetti o se il vostro software è scalabile, se avete un aumento del traffico di rete
e vedete che il vostro tempo di risposta si sta deteriorando.
È anche possibile monitorare i thread e le informazioni sugli oggetti per l'elaborazione parallela, per vedere cosa succede
in certi thread e cosa succede in un altro thread.
Questo vi aiuterà a diagnosticare qualsiasi tipo di problema del filo.
Alcuni altri strumenti di debug comuni che potete utilizzare per trovare e risolvere gli errori.
È possibile utilizzare la gestione delle eccezioni.
Molti linguaggi di programmazione prevedono la gestione delle eccezioni.
Sfortunatamente, il C non ha un gestore di eccezioni in grado di prevenire gli arresti anomali e di fare molte cose in fase
di esecuzione.
Non è applicabile a tutti, ma è comunque una buona cosa da capire.
Blocchi Trycatch, cose del genere.
Analizzatori statici.
Sono disponibili molti analizzatori statici per C.
Analizzare il codice sorgente senza l'eseguibile vero e proprio.
Non è necessario che il programma venga eseguito.
Esamina riga per riga il codice sorgente.
Mentre analizza il codice sorgente, cerca eventuali problemi noti.
Quindi può controllare la semantica.
Può assicurarsi che.
Tutto qui.
Non si hanno variabili non inizializzate se si alloca nuova memoria e la si cancella.
Se c'è del codice morto che non viene effettivamente eseguito, è possibile eliminarlo.
Analizza anche aspetti come le condizioni di gara e i deadlock.
Dove lavoro impieghiamo un paio di analizzatori statici.
Ne abbiamo uno chiamato Coverity, piuttosto popolare, e c'è uno strumento di sonar del codice che usiamo anche noi, e lo eseguiamo
su tutta la nostra linea di base, su tutto il nostro set di sorgenti.
Ogni volta che introduciamo nuovi file e nuovo codice, lo strumento verrà eseguito su quel codice e sarà in grado di identificare
immediatamente i problemi del codice, come variabili non inizializzate, perdite di memoria e così via.
Non analizza la sintassi.
A questo serve il compilatore.
Esiste anche una serie di suite di test che eseguono una serie di test completi end-to-end del sistema che possono
essere eseguiti sul software.
I test sono sempre importanti, ma se è possibile automatizzarli in qualche modo per eseguire determinati test ogni volta
che si esegue una nuova compilazione, ad esempio, ciò può essere molto utile e può effettivamente prevenire
gli errori, ma anche aiutare a diagnosticarli.
Eseguire il debug del programma dopo l'arresto anomalo.
Parleremo di una cosa chiamata stack di chiamate.
Si tratta di un meccanismo molto utile, soprattutto in un linguaggio come il C, dove si verifica un arresto anomalo e l'unica informazione
che si ottiene è qualcosa come un errore di segmentazione.
Quando si verifica l'arresto anomalo, molto spesso, a seconda del modo in cui si è verificato, viene generato
un file di core, che può essere analizzato per esaminare lo stack delle chiamate e vedere esattamente dove è morto il programma.
Vi indicherà la riga di codice in cui il programma è morto.
Impareremo quindi a conoscere lo stack delle chiamate.
Per quanto riguarda l'analisi dei file principali, si tratta di una tecnica più avanzata.
Ma in C è possibile generare un file core e analizzarlo.
Si tratta di una tecnica un po' più avanzata, ma è un altro modo per eseguire il debug del software.
E per quanto riguarda la prevenzione degli errori?
Sappiamo che il debug consiste nel trovare e correggere gli errori, ma se riuscite a prevenirli è ancora meglio.
Uno dei modi per prevenire gli errori è scrivere codice di alta qualità.
Questo non è un aspetto su cui si concentrano molti ingegneri del software.
Molti ingegneri del software scrivono il codice e, finché funziona, non
si preoccupano d'altro o finché l'output è corretto, si considerano a posto.
Ma esiste anche un codice di scarsa qualità e non è il caso di scriverlo.
Ho dimostrato alcuni di questi aspetti durante le lezioni, ma cose come l'uso di nomi di variabili significativi sono
molto importanti.
Oppure se si scrive un codice inefficiente in cui si usano i loop forse più del necessario, o si usa un'istruzione
if o non è necessario farlo.
Tutti questi tipi di cose costituiscono codice di scarsa qualità.
Se avete una funzione che fa altre 100 cose e non è coesa, se avete 5000 righe in una funzione, se
il vostro codice non è organizzato in modo modulare o se avete molte dipendenze tra
le funzioni, ancora una volta, tutto questo è codice di scarsa qualità e dovete sforzarvi di non farlo.
Si vogliono impiegare tecniche in cui il programma è organizzato.
È facile da mantenere, è altamente coesivo, ha un accoppiamento ridotto e si usano nomi di variabili significativi.
Molto, molto importante.
Ancora una volta, è molto importante anche perché la fase di mantenimento è molto, molto costosa.
Se si scrive codice di scarsa qualità, diventa molto più difficile mantenerlo.
È più difficile isolare gli errori e aggiungere nuove funzionalità.
Quindi, quando scrivete il vostro codice, impiegate buone tecniche di alta qualità.
Test unitari.
I test unitari aiutano enormemente a prevenire gli errori.
I test unitari vengono eseguiti di solito automaticamente durante la compilazione e possono aiutare a evitare la regressione.
Questo è uno dei fattori più importanti.
La regressione è quando si scrive nuovo codice e si introduce un bug in qualcosa che prima funzionava.
Avete rotto il vecchio codice.
Non è il caso di farlo.
Se un software funziona e poi qualcosa di nuovo che avete fatto lo rompe, volete essere immediatamente avvisati
e i test unitari possono aiutarvi a farlo, perché i test unitari vengono eseguiti sul vecchio codice e dicono: "Ehi, questo
funzionava, ora sta fallendo".
Può anche trovare errori nel nuovo codice prima che venga consegnato, perché, ancora una volta, viene eseguito dopo la compilazione
e vi dirà immediatamente che qualcosa non va.
Esiste un concetto di sviluppo guidato dai test che sta diventando molto, molto popolare.
In questo caso si scrivono prima i test e poi si sviluppa il codice.
L'obiettivo è che quando si scrive il primo test, questo fallisca e si scriva il codice per
farlo passare.
Il TDD presenta molti vantaggi ed è una sorta di modo di pensare inverso.
Normalmente, quando si scrive del codice, si scrive prima il codice e poi si scrive il test.
Ma con il TDD, in realtà, si ha un modo diverso di pensare, per cui si lavora in pezzi molto piccoli
e si tende a scrivere codice molto coeso e non si ha il codice, non si hanno molte dipendenze
perché, indovinate un po'?
Se siete in grado di testare il codice, significa che il codice non ha tante dipendenze.
Se il vostro test unitario è molto, molto grande e state prendendo in giro tutte queste cose diverse,
di solito è un grande indicatore che il vostro codice è molto, molto dipendente da altre cose.
Quindi, impiegando il TDD, si è costretti a scrivere codice molto libero, senza dipendenze, e
a far sì che le funzioni siano molto coese.
I vantaggi del TDD sono numerosi.
È inoltre necessario fornire una buona documentazione e fare una pianificazione adeguata.
Non limitatevi a immergervi nel codice e a iniziare l'implementazione.
Scrivete il vostro progetto su carta.
Utilizzare lo pseudocodice.
Giusto.
Pianificare il codice.
Se si pianifica il codice, si comprendono i requisiti e si ha una buona progettazione, si possono
evitare molti, molti errori.
L'ho detto in tutto il corso, ma è molto, molto importante avere un approccio di
tipo divide et impera, lavorare a piccoli passi e testare costantemente dopo ogni passo, non scrivere 1000
righe di codice e poi dire, ok, compila e testa.
Non è un buon approccio.
Evitare troppi cambiamenti in una volta sola.
Quando si apportano modifiche, applicarle in modo incrementale, aggiungere una modifica e poi testarla a fondo prima di iniziare
la fase successiva.
Questo può aiutare a ridurre ogni tipo di bug e a limitare il numero di problemi.
In questo modo, se si verifica un bug, si sa subito dove si trova nel codice, perché si è appena compilato
e si è appena aggiunta quella riga o quel numero di righe.
Ancora una volta, non posso sottolineare l'importanza di eseguire il debug scrivendo codice di alta qualità e prevenendo gli errori.
Queste tecniche di risoluzione dei problemi vi faranno risparmiare un sacco di tempo e vi renderanno un programmatore di livello superiore
molto migliore.
Nelle prossime lezioni, quindi, vorrei parlare di alcuni degli errori più comuni che si riscontrano nel linguaggio di programmazione
c.
Inoltre, vorrei parlare un po' dello stack delle chiamate.
Voglio passare in rassegna il debugger e introdurre le opzioni di menu e il modo in cui è possibile arrestare ed eseguire
gli orologi e così via.
Voglio anche aiutarvi a identificare alcuni errori comuni del compilatore, per capire come interpretare i compilatori, le avvertenze e gli errori
del compilatore.
Cosa significa se il compilatore dice questo?
Cosa significa se il compilatore dà questo avviso?
Grazie.