DOUG LLOYD: Va bene GDB. Di cosa si tratta esattamente? Così GDB, che sta per il Debugger GNU, è uno strumento davvero fantastico che possiamo utilizzare per aiutarci a eseguire il debug nostri programmi, o scoprire dove sono le cose che non va nei nostri programmi. GDB è incredibilmente potente, ma l'uscita e l'interazione con essa può essere un po 'criptico. Di solito è un tool a riga di comando, e si può buttare un sacco di messaggi a voi. E può un po 'difficile analizzare esattamente cosa sta succedendo. Passi per fortuna, abbiamo preso per risolvere questo problema per voi come si lavora attraverso CS50. Se non si utilizza la grafica debugger, che il mio collega Dan Armandarse ha parlato abbastanza un po 'su di un video che dovrebbe essere qui in questo momento, potrebbe essere necessario di utilizzare questi riga di comando strumenti per lavorare con GDB. Se stai lavorando nella CS50 IDE, non è necessario fare questo. Ma se non siete lavorando in CS50 IDE, magari utilizzando una versione di CS50 Appliance, o impiega un altro Linux Sistema con GDB installato su di esso, potrebbe essere necessario utilizzare questi strumenti da riga di comando. E dal momento che si potrebbe hanno a che fare questo, è utile solo per capire come GDB funziona dalla riga di comando. Ma ancora una volta, se siete utilizzando l'IDE CS50, si può utilizzare il debugger grafico che è costruito nell'IDE. Quindi, per far funzionare le cose con GDB, per avviare il debug processo di una particolare il programma, tutto quello che dovete fare è di tipo GDB seguito dal nome del programma. Così, per esempio, se il programma è ciao, si digiterà GDB ciao. Quando lo fate, si sta andando per tirare su l'ambiente GDB. Il prompt cambierà, e invece di essere ciò che di solito è quando si digita le cose ai line-- comando ls, cd-- tutto il vostro tipico Comandi di Linux, il prompt cambierà in, probabilmente, qualcosa come parentesi GDB parentesi. Questo è il tuo nuovo prompt GDB, perché sei dentro l'ambiente GDB. Una volta all'interno di tale ambiente, ci sono due importanti comandi che probabilmente utilizza nel seguente ordine. Il primo è b, che è l'abbreviazione di pausa. E dopo aver digitato b, in genere digitare il nome di una funzione, o se vi capita di sapere intorno a che cosa il numero di riga il programma sta iniziando a comportarsi un po 'strano, è possibile digitare una linea numero di lì. Cosa b, o rottura, fa è che consente al programma per eseguire fino a un certo punto, cioè, il nome della funzione specificato o la linea numero specificato. E a quel punto, si blocca l'esecuzione. Questa è una cosa veramente buona, perché una volta che l'esecuzione è stato congelato, si può cominciare a molto lentamente passo attraverso il vostro programma. In genere, se si è stati in esecuzione i programmi, sono piuttosto breve. Di solito, si digita barra puntino qualunque il nome del programma è, premere Invio, e prima di poter lampeggiare, la vostra programma è già terminato. Non è davvero un sacco di tempo per provare e capire cosa sta andando male. Quindi davvero essere in grado di rallentare cose giù impostando un punto di rottura con b, e poi intervenendo. Poi, una volta che hai impostato la tua vacanza punto, è possibile eseguire il programma. E se avete qualunque argomenti della riga di comando, si specifica qui, non quando si digita GDB vostro nome del programma. Si specifica tutta la riga di comando argomenti prendendo r, o correre, e poi gli argomenti della riga di comando qualsiasi è necessario all'interno del vostro programma. Ci sono un certo numero di altri veramente comandi importanti e utili all'interno dell'ambiente PIL. Quindi lasciatemi rapidamente superare alcuni di essi. Il primo è n, che è l'abbreviazione per il prossimo, e si può digitare successiva invece di n, entrambi avrebbero funzionato. Ed è solo la stenografia. E come probabilmente avete già ottenuto utilizzato per, essere in grado di scrivere le cose più breve è generalmente migliore. E che cosa farà è che sarà avanzare di un blocco di codice. Così muoverà avanti fino a quando una chiamata di funzione. E allora invece di tuffarsi in quella funzione e passando attraverso tutti che le funzioni codice, sarà solo avere la funzione. La funzione verrà chiamata. Si farà tutto ciò che il suo lavoro è. Si restituirà un valore di la funzione che lo ha chiamato. E allora ti passa al riga successiva di tale funzione chiamante. Se si vuole fare un passo all'interno della funzione, invece di avere esso esegue, soprattutto se si pensa che il problema potrebbe trovarsi all'interno di quella funzione, si potrebbe, naturalmente, impostare una pausa punto all'interno di tale funzione. Oppure, se siete già in esecuzione, è possibile usare s fare un passo in avanti di una riga di codice. Quindi questo sarà un passo dentro e tuffarsi in funzioni, invece di avere solo la execute e continuando nella funzione che ci si trova per il debug. Se mai voglia di sapere il valore di una variabile, è possibile digitare p, o Stampa, e poi il nome della variabile. E che stamperanno a voi, all'interno dell'ambiente GDB, il nome della variabile, che you-- scusate me-- il valore della variabile che hai chiamato. Se volete conoscere i valori di ogni variabile locale accessibile da dove vi trovate nella vostra il programma, è possibile digitare informazioni locali. E 'molto più veloce di digitando p e poi tutto ciò che, elencando tutti i variabili che si conosce l'esistenza. È possibile digitare informazioni locali, ed è stamperà fuori tutto per voi. Il prossimo è bt, che è abbreviazione di Torna Trace. Ora, in generale, soprattutto all'inizio del CS50, non sarà davvero avere occasione utilizzare bt, o Indietro Trace, perché non stai con funzioni che chiamano altre funzioni. Si potrebbe avere una chiamata principale la funzione, ma questo è probabilmente. Non è necessario che altre funzioni chiamare un'altra funzione, che chiama un'altra funzione, e così via. Ma, come i programmi si fanno più complesso, e in particolare quando si inizia a lavorare con la ricorsione, tracce indietro può essere un modo molto utile per farti tipo di ottenere un contesto per cui Io sono nel mio programma. Quindi dici che hai scritto il tuo codice, e si sa che principale chiama una funzione f, che chiama una funzione g, che chiama una funzione h. Così abbiamo diversi strati di nidificazione succedendo qui. Se sei dentro di l'ambiente di GDB, e sai che il tuo interno di ore, ma si dimentica su ciò che hai da dove are-- è possibile digitare bt, o traccia indietro, e stamperà h, g, f principale, insieme ad altre informazioni, quali ti dà un indizio che, principale OK chiamato f, f chiamata g, g chiamato h, ed è lì che ho attualmente sono nel mio programma. Così può essere davvero utile, tanto più che il criptico-ness di GDB diventa un po 'opprimente, a scoprire esattamente dove stanno le cose. Infine, quando il programma è fatto, o quando hai finito il debug e si desidera allontanarsi dall'ambiente GDB, è utile sapere come uscirne. È possibile digitare q, o Esci, per uscire. Ora, prima di video di oggi Ho preparato un programma buggy chiamato buggy1, che ho compilato da un file noto come buggy1.c. Come ci si potrebbe aspettare, questo programma è infatti buggy. Qualcosa va storto quando provo ed eseguirlo. Ora, purtroppo, ho inavvertitamente cancellato il mio file buggy1.c, così in modo per me per capire cosa sta andando male con questo programma, Ho intenzione di dover utilizzare GDB sorta di cieca, cercando di per navigare attraverso questo programma per capire esattamente cosa sta andando male. Ma utilizzando solo gli strumenti abbiamo già imparato a conoscere, si può tranquillamente figura esattamente quello che è. Quindi cerchiamo di testa verso CS50 IDE e dare un'occhiata. Ok, siamo qui nella mia CS50 ambiente IDE, e io lo zoom in un po ' così si può vedere un po 'di più. Nella mia finestra di terminale, se vi elenco il contenuto del mio attuale direttore con ls, vedremo che io avere un paio di file di origine qui, tra cui il precedentemente discusso buggy1. Che cosa accade esattamente quando Provo e corro buggy1. Beh diciamo scoprirlo. Digito barra puntino, buggy, e mi ha colpito Invio. Errori di segmentazione. Questo non va bene. Se vi ricordate, un segmentation fault tipicamente si verifica quando si accede memoria che non ci è permesso di toccare. Abbiamo in qualche modo raggiunto al di fuori dei limiti di ciò che il programma, la compilatore, ci ha dato. E così già questo è un indizio per mantenere nella casella degli strumenti mentre iniziamo il processo di debug. Qualcosa è andato un po 'sbagliato qui. Va bene, quindi cerchiamo di partenza l'ambiente GDB e vedere se siamo in grado di capire che cosa è esattamente il problema. Ho intenzione di cancellare il mio schermo, e ho intenzione di scrivere GDB ancora una volta, per accedere all'ambiente GDB, e il nome del programma che voglio eseguire il debug, buggy1. Abbiamo un piccolo messaggio, la lettura simboli buggy1, fatto. Tutto questo significa è tirato insieme tutto il codice, e ora è stato caricato in GDB, ed è pronto a partire. Ora, che cosa voglio fare? Ti ricordi quello che il primo passo è tipicamente dopo che sono dentro di questo ambiente? Speriamo che detto insieme un punto di rottura, perché infatti questo è ciò che voglio fare. Ora, io non ho il codice sorgente di questo di fronte a me, che è probabilmente Non il tipico caso d'uso, tra l'altro. Probabilmente lo farà. Quindi, questo è un bene. Ma a patto che non, che cosa è la una funzione che si sa esiste in ogni singolo programma C? Non importa quanto grande o complicato è, questa funzione sicuramente esiste. Main, giusto? Quindi in mancanza di ogni altra cosa, ci si può impostare un punto di interruzione a principale. E ancora, ho potuto solo digitare rompere principale, invece di b. E se siete curiosi, se mai digitare un comando lungo e poi rendersi conto che si digitato la cosa sbagliata, e si vuole sbarazzarsi di tutto quanto ho appena fatto, si può prendere il controllo di U, che sarà cancellare tutto e vi riporterà all'inizio delle linee del cursore. Molto più veloce di appena tenere premuto il eliminare o colpendola volte e mazzo sopra. Quindi verrà impostato un punto di interruzione a principale. E come si può vedere, si dice che abbiamo impostare un punto di interruzione a file di buggy1.c, ea quanto pare la prima linea di codice di principale è la linea di sette. Ancora una volta, non abbiamo il file di origine qui, ma darò per scontato che si tratta di dirmi la verità. E poi, io sto solo cercando ed eseguire il programma, r. L'avvio del programma. Va bene, quindi questo messaggio è un po 'criptico. Ma in fondo che cosa è accadendo qui è che è solo mi dice ho colpito la mia pausa punto, rottura punto numero 1. E poi, quella riga di codice, Nessun file o directory con questo nome. L'unica ragione per cui Sto vedendo che il messaggio è perché ho inavvertitamente cancellato il mio file buggy.c. Se il mio file di buggy1.c esistito nella directory corrente, che proprio la linea ci sarebbe in realtà dimmi che cosa la riga di codice si legge letteralmente. Purtroppo, ho cancellato. Stiamo andando ad avere per tipo di navigazione attraverso questo un po 'più cieca. Ok, vediamo, cosa voglio fare qui? Beh, mi piacerebbe sapere che cosa locali variabili forse sono disponibili per me. Ho iniziato il mio programma. Vediamo cosa potrebbe essere già inizializzato per noi. I tipo Info gente del posto, nessuna locali. Va bene, in modo che non lo fa dammi una tonnellata di informazioni. Potrei provare e stampare una variabile, ma io non conosco i nomi delle variabili. Potrei provare una traccia indietro, ma io sono dentro di principale, quindi so che non ho fatto un'altra chiamata di funzione al momento. Così sembra che le mie uniche opzioni sono a utilizzare n o giù di lì e iniziare a tuffarsi. Ho intenzione di utilizzare n. Così ho tipo n. Oh mio Dio, che cosa sta succedendo qui. Programma ha ricevuto segnali, SIGSEGV segmentation fault, e poi un sacco di roba. Sono già sopraffatto. Beh, c'è in realtà un molto da imparare qui. Che cosa ci dice questo? Quello che ci dice è, questo programma è per farlo, ma non ha ancora, colpa seg. E in particolare, sto andando per ingrandire ancora di più qui, è in procinto di Seg colpa su qualcosa chiamato strcmp. Ora, potremmo non abbiamo discusso questa funzione estesamente. Ma è-- perché non stiamo andando per parlare di ogni funzione che esiste nello standard C library-- ma sono tutti a vostra disposizione, soprattutto se si prende un guardare reference.cs50.net. E strcmp è davvero potente funzione che esiste dentro dell'intestazione string.h file, che è un'intestazione File che è dedicato alle funzioni che lavorano con e manipolare le stringhe. E in particolare, ciò che fa è strcmp confronta i valori di due stringhe. Quindi sono sul punto di segmentazione guasto su una chiamata a strcmp sembra. Mi ha colpito n, e infatti ottengo il messaggio, programma terminato con il segnale SIGSEGV segmentation fault. Così ora Io in realtà ho seg guasto, e il mio programma ha abbastanza molto efficace rinunciato. Questa è la fine del programma. Si è rotto, si è schiantato. Quindi non era molto, ma io in realtà ha fatto imparare un po ' da questa piccola esperienza. Che cosa ho imparato? Beh, il mio programma si blocca praticamente subito. Il mio programma va in crash una chiamata a strcmp, ma io non hanno alcun variabili locali nel mio il programma nel momento in cui si blocca. Così che cosa stringa o stringhe, potrei essere il confronto. Se non ho alcun locale variabili, si potrebbe Suppongo che ci have-- forse è un variabile globale, che potrebbe essere vero. Ma in generale, sembra come sto paragonando a qualcosa che non esiste. Quindi cerchiamo di indagare che un po 'oltre. Quindi ho intenzione di cancellare il mio schermo. Ho intenzione di uscire fuori dalla Ambiente GDB per un secondo. E sto pensando, OK, quindi non c'è senza variabili locali nel mio programma. Mi chiedo se forse dovrei passare in una stringa come argomento della riga di comando. Così facciamo solo testare il tutto. Io non ho fatto prima. Vediamo se forse se corro questo programma con un argomento da riga di comando che funziona. Eh, no segmentation fault lì. E 'appena mi ha detto che ho capito. Quindi forse è la correzione qui. E in effetti, se vado indietro e guardare il codice sorgente per buggy1.c, sembra che quello che sto facendo è Sto facendo una chiamata a strcmp senza verificare se infatti argv [1] esiste. Questo è in realtà la codice sorgente per buggy1.c. Che cosa ho veramente bisogno di fare qui per fissare il mio programma, supponendo che ho la presentare di fronte a me, è per aggiungere solo un controllo per fare Assicurarsi che argc è pari a 2. Quindi questo esempio, ancora una volta, come ho detto, è un pò forzato, giusto? Non stai in genere andando a eliminare accidentalmente il codice sorgente e poi a provare e testare il programma. Ma si spera, ha dato si un'illustrazione dei tipi di cose che si potrebbe pensare di come si sta debugging del programma. Qual è lo stato delle cose qui? Quali sono le variabili che fare avere accesso a me? Dove esattamente è il mio programma schiantarsi, su quale linea, su cosa chiamata alla quale funzione? Che tipo di indizi fa che mi danno? E questo è esattamente il tipo di mentalità che si dovrebbe essere sempre in quando sei pensando di debug dei programmi. Sono Doug Lloyd. Questo è CS50.