Sei sulla pagina 1di 10

Appendice G Utilizzare il Debugger GNU

Obiettivi
Essere in grado di utilizzare il comando run per eseguire un programma nel debugger. Essere in grado di utilizzare il comando break per inserire un breakpoint. Essere in grado di utilizzare il comando continue per continuare l'esecuzione. Essere in grado di utilizzare il comando print per valutare le espressioni. Essere in grado di utilizzare il comando set per cambiare il valore delle variabili durante l'esecuzione del programma. Essere in grado di utilizzare i comandi step, finish e next per controllare l'esecuzione. Essere in grado di utilizzare il comando watch per controllare come un elemento dei dati viene modificato durante l'esecuzione del programma. Essere in grado di utilizzare il comando delete per rimuovere un breakpoint o un watchpoint.

G.1 Introduzione
Nel Capitolo 2 avete imparato che esistono due tipi di errori, ovvero, errori di compilazione ed errori logici ed avete imparato come eliminare i primi dal vostro codice. Gli errori logici non impediscono che un programma venga compilato con successo, ma possono far s che il programma stesso produca dei risultati erronei al momento dell'esecuzione. GNU fornisce del software detto debugger che vi permette di controllare l'esecuzione dei vostri programmi in modo da individuare ed eliminare gli errori logici. Il debugger uno dei pi importanti strumenti di sviluppo di programmi. Molti IDE forniscono i propri debugger che sono simili a quello fornito da GNU oppure forniscono un'interfaccia grafica al debugger della GNU. Questa appendice illustra le caratteristiche chiave di quest'ultimo. L'Appendice G invece discute le caratteristiche e le capacit del debugger del Visual Studio. Il nostro C Resource Center (www.deitel.com/c/) fornisce dei link a dei tutorial che possono essere di aiuto agli studenti ed ai docenti per familiarizzare con i debugger forniti da vari altri strumenti di sviluppo.

G.2 I breakpoint e i comandi run, stop, continue e print


Iniziamo illustrando i breakpoint, che sono dei marcatori che possono essere impostati in ogni linea di codice eseguibile. Quando l'esecuzione del programma raggiunge un breakpoint, viene effettuata una pausa, permettendovi di esaminare i valori delle variabili per aiutarvi a stabilire se ci sia un errore logico. Per esempio, potete esaminare il valore di una variabile che memorizza il risultato di un calcolo per stabilire se il calcolo stato effettuato correttamente. Si noti che tentare di inserire un breakpoint in corrispondenza di una linea di codice che non sia eseguibile (come un commento) imposter il breakpoint alla prossima linea eseguibile di codice nella relativa funzione. Per illustrare le caratteristiche del debugger, utilizziamo il programma in Figura G.1, che trova il massimo di tre interi. L'esecuzione inizia in corrispondenza del main (righe 822 della Figura G.1). I tre interi vengono inseriti con la scanf (riga 15). In seguito, gli interi sono passati a maximum (riga 19), che ne determina il massimo. Quest'ultimo il valore restituito al main dal comando return in maximum (riga 38). Il valore restituito viene poi visualizzato per mezzo del comando printf (riga 19).
1 /* Fig. G.1: figH_01.c 2 Trovare il massimo di tre interi */ 3 #include <stdio.h> 4 5 int maximum( int x, int y, int z ); /* prototipo di funzione */ 6 7 /* lesecuzione del programma inizia dalla funzione main */ 8 int main( void ) 9{ 10 int number1; /* primo intero */ 11 int number2; /* secondo intero */ 12 int number3; /* terzo intero */

Copyright (C) 2010 Apogeo

13 printf( "Enter three integers: " ); 14 15 scanf( "%d%d%d", &number1, &number2, &number3 ); 16 17 /* number1, number2 e number3 sono gli argomenti 18 della chiamata di funzione a maximum */ 19 printf( "Maximum is: %d\n", maximum( number1, number2, number3 ) ); 20 21 return 0; /* indica che il programma terminato con successo */ 22 } /* fine della funzione main */ 23 24 /* Definizione della funzione maximum */ 25 /* x, y e z sono i parametri */ 26 int maximum( int x, int y, int z ) 27 { 28 int max = x; /* si assuma che x sia il massimo */ 29 if ( y > max ) { /* se y maggiore di max, assegna y a max */ 30 31 max = y; 32 } /* end if */ 33 if ( z > max ) { /* se z maggiore di max, assegna z a max */ 34 35 max = z; 36 } /* end if */ 37 return max; /* max il valore massimo */ 38 39 } /* fine della funzione maximum */

Fig. G.1 | Determinare il massimo di tre interi.

Nei passi seguenti utilizzerete i breakpoint e vari comandi del debugger per esaminare il valore della variabile number1 dichiarata nella riga 10 della Figura G.1 1. Compilare il programma per il debugging. Per utilizzare il debugger, dovete compilare il vostro programma con l'opzione -g, che genera dell'informazione addizionale necessaria affinch il debugger vi aiuti a trovare gli errori nei vostri programmi. Per far ci, digitate
gcc -g figH_01.c

2. Eseguire il debugger. Digitate gdb ./a.out (Figura G.2). Il comando gdb fa partire il debugger e visualizza il prompt (gdb) al quale potete impartire i comandi. 3. Far girare un programma all'interno del debugger. Eseguite il programma per mezzo del debugger digitando run (Fig. G.3). Se non avete impostato nessun breakpoint prima di far girare il vostro programma nel debugger, esso eseguir fino al completamento.

$ gdb ./a.out GNU gdb 6.8-debian Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu"... (gdb)

Fig. G.2 | Far partire il debugger per eseguire il programma.


(gdb) run Starting program: /home/user/AppJ/a.out Enter three integers: 22 85 17 Max is 85 Program exited normally. (gdb)

Fig. G.3 | Eseguire il programma senza breakpoint impostati.

Copyright (C) 2010 Apogeo

4. Inserire dei breakpoint utilizzando il debugger GNU. Impostate un breakpoint nella riga 14 di FigH_01.c digitando break 14. Il comando break inserisce un breakpoint in corrispondenza del numero di riga specificato come suo argomento (ad esempio, 22, 85, e 17). Potete impostare tanti breakpoint quanti ne ritenete necessari: ognuno di essi sar identificato in base all'ordine in cui stato creato. Il primo breakpoint sar noto come Breakpoint 1. Impostate un altro breakpoint in corrispondenza della riga 19 digitando break 19 (Figura G.4). Questo nuovo breakpoint sar noto come Breakpoint 2. Quando il programma girer, l'esecuzione verr sospesa in corrispondenza di ogni linea che contenga un breakpoint ed il debugger entrer in break mode. I breakpoint possono essere impostati anche dopo che il processo di debugging iniziato. [Nota: Se non avete un listato con i numeri di riga del vostro codice, potete usare il comando list per visualizzarlo decorato con i numeri di riga. Per ulteriori informazioni sul comando list digitate help list al prompt gdb.]

(gdb) break 14 Breakpoint 1 at 0x80483e5: file figH_01.c, line 14. (gdb) break 19 Breakpoint 2 at 0x8048440: file figH_01.c, line 19.

Fig. G.4 | Impostare due breakpoint nel programma. 5. Eseguire il programma ed iniziare il processo di debugging. Digitate run per eseguire il vostro programma ed iniziare il processo di debugging (Figura G.5). Il debugger entrer in break mode quando l'esecuzione raggiunger il breakpoint in riga 14. A tal punto il debugger vi notificher che il breakpoint stato raggiunto e visualizzer il codice sorgente di quella riga (14), che consister nel prossimo comando da eseguire.
(gdb) run Starting program: /home/user/AppJ/a.out Breakpoint 1, main() at figH_01.c:14 14 scanf("%d%d%d", &number1, &number2, &number3); (gdb)

Fig. G.5 | Eseguire il programma fino al raggiungimento del primo breakpoint.

6. Usare il comando continue per riprendere l'esecuzione. Digitate continue. Il comando continue fa in modo che il programma riprenda a girare fino al raggiungimento del prossimo breakpoint (riga 19). Inserite 22, 85, e 17 al prompt. Il debugger vi avviser quando l'esecuzione avr raggiunto il secondo breakpoint (Figura G.6). Notate che il normale output del programma figH_01 compare fra i messaggi del debugger.

(gdb) continue Continuing. Enter three integers: 22 85 17 Breakpoint 2, main() at figH_01.c:19 19 printf("Max is %d\n", maximum(number1, number2, number3)); ( gdb)

Fig. G.6 | Continuare l'esecuzione fino al raggiungimento del secondo breakpoint.

7. Esaminare il valore di una variabile. Digitate print number1 per visualizzare il valore corrente memorizzato nella variabile number1 (Figura G.7). Il comando print vi permette di sbirciare all'interno del computer il valore di una delle vostre variabili. Ci vi pu essere di aiuto nell'individuare ed eliminare gli errori logici nel vostro codice. In questo caso il valore della variabile 22, ovvero, il valore che avete inserito e che stato assegnato alla variabile number1 nella riga 15 della Figura G.1.

Copyright (C) 2010 Apogeo

(gdb) print number1 $1 = 22 (gdb)

Fig. G.7 | Visualizzare i valori delle variabili. 8. Utilizzare le variabili di utilit (in inglese: convenience variable). Quando usate print, il risultato viene memorizzato in una variabile di utilit come $1. Le variabili di utilit sono variabili temporanee create dal debugger e denominate utilizzando il carattere del dollaro seguito da un intero. Le variabili di utilit possono essere utilizzate per effettuare dei calcoli aritmetici e per valutare delle espressioni booleane. Digitate print $1. Il debugger visualizzer il valore di $1 (Figura G.8), che contiene il valore di number1. Notate che visualizzare il valore di $1 creer una nuova variabile di utilit, ovvero, $2.
(gdb) print $1 $2 = 22 (gdb)

Fig. G.8 | Visualizzare una variabile di utilit (convenience variable). 9. Continuare l'esecuzione del programma. Digitate continue per continuare l'esecuzione del programma. Siccome il debugger non incontrer ulteriori breakpoint, continuer l'esecuzione, terminando prima o poi. (Figura G.9).
(gdb) continue Continuing Max is 85 Program exited normally (gdb)

Fig. G.9 | Terminare l'esecuzione del programma. 10. Eliminare un breakpoint. Potete visualizzare una lista di tutti i breakpoint del programma digitando info break. Per eliminare un breakpoint, digitate delete, seguito da uno spazio e dal numero del breakpoint da rimuovere. Rimuovete il primo breakpoint digitando delete 1. Rimuovete anche il secondo breakpoint. A questo punto digitate info break per ottenere l'elenco dei rimanenti breakpoint del programma. Il debugger dovrebbe indicarvi che non ci sono dei breakpoint impostati (Figura G.10).
(gdb) info break Num Type Disp Enb Address 1 breakpoint keep y 0x080483e5 breakpoint already hit 1 time 2 breakpoint keep y 0x08048799 breakpoint already hit 1 time (gdb) delete 1 (gdb) delete 2 (gdb) info break No breakpoints or watchpoints (gdb) What in main at figH_01.c:14 in main at figH_01.c:19

Fig. G.10 | Visualizzare e rimuovere i breakpoint. 11. Eseguire il programma senza breakpoint. Digitate run per eseguire il programma. Inserite i valori 22, 85, e 17 al prompt. Siccome avete eliminato con successo i due breakpoint, l'output del programma verr visualizzato senza che il debugger rientri in break mode (Figura G.11). 12. Utilizzare il comando quit. Utilizzate il comando quit per terminare la sessione di debugging (Figura G.12). Questo comando fa in modo che il debugger termini la sua esecuzione.
(gdb) run Starting program: /home/user/AppJ/a.out Enter three integers: 22 85 17 Max is 85 Program exited normally. (gdb)

Fig. G.11 | Esecuzione del programma senza breakpoint impostati.

Copyright (C) 2010 Apogeo

(gdb) quit $

Fig. G.12 | Uscire dal debugger utilizzando il comando quit.

In questa sezione avete utilizzato il comando gdb per far partire il debugger ed il comando run per iniziare l'attivit di debugging di un programma. Avete impostato un breakpoint in corrispondenza di una particolare numero di riga nella funzione main. Il comando break pu anche essere utilizzato per impostare un breakpoint in corrispondenza di una riga in un altro file o in una particolare funzione. Digitando break, seguito dal nome del file, dal carattere di due punti e dal numero di riga, si imposter un breakpoint in corrispondenza di una riga in un altro file. Digitando break, seguito dal nome di una funzione, si far in modo che il debugger entri in break mode ogni volta che tale funzione verr richiamata. Inoltre in questa sezione avete visto come il comando help list fornisca ulteriori informazioni sul comando list. Se avete dei dubbi sul debugger o su qualcuno dei suoi comandi, digitate help o help seguito dal nome del comando per ottenere maggiori informazioni. Infine avete esaminato le variabili per mezzo del comando print ed avete rimosso i breakpoint con il comando delete. Avete imparato ad utilizzare il comando continue per proseguire l'esecuzione dopo il raggiungimento di un breakpoint ed il comando quit per terminare l'esecuzione del debugger.

G.3 I comandi print e set


Nella sezione precedente avete imparato ad utilizzare il comando print del debugger per esaminare il valore di una variabile durante l'esecuzione del programma. In questa sezione imparerete ad utilizzare il comando print per esaminare il valore di espressioni pi complesse. Imparerete anche il comando set, che vi permetter di assegnare nuovi valori alle variabili. Assumeremo che stiate lavorando nella directory contenente gli esempi di questa appendice e che li abbiate compilati per il debugging con l'opzione -g del compilatore. 1. Iniziare il debugging. Digitate gdb ./a.out per far partire il debugger GNU. 2. Inserire un breakpoint. Impostate un breakpoint in corrispondenza della riga 19 nel codice sorgente digitando break 19 (Figura G.13).
(gdb) break 19 Breakpoint 1 at 0x8048412: file figH_01.c, line 19. (gdb)

Fig. G.13 | Impostare un breakpoint nel programma. 3. Eseguire il programma e raggiungere un breakpoint. Digitate run per iniziare il processo di debugging (Figura G.14). Ci far s che main esegua fino al raggiungimento del breakpoint in corrispondenza della riga 19. Tale fatto sospender l'esecuzione del programma mettendolo in break mode. Il comando in riga 19 il prossimo comando che verr eseguito.

(gdb) run Starting program: /home/user/AppJ/a.out Enter three integers: 22 85 17 Breakpoint 1, main() at figI_01.c:19 19 printf("Max is %d\n", maximum(number1, number2, number3)); (gdb)

Fig. G.14 | Eseguire il programma fino al raggiungimento del breakpoint in riga 19.

Copyright (C) 2010 Apogeo

4. Valutare le espressioni aritmetiche e booleane. Ricordate dalla Sezione G.2 che, una volta che il debugger entra in break mode, potete esplorare i valori delle variabili del programma utilizzando il comando print. Potete utilizzare print anche per valutare le espressioni aritmetiche e booleane. Digitate print number1 - 2. Questa espressione restituir il valore 20 (Figura G.15), ma non effettua alcun cambiamento del valore di number1. Digitate print number1 == 20. Le espressioni che contengono il simbolo == restituiscono 0 se il comando falso e 1 se il comando vero. In questo caso il valore restituito sar 0 (Figura G.15) dato che number1 contiene ancora 22.
(gdb) print number1 2 $1 = 20 (gdb) print number1 == 20 $2 = 0 (gdb)

Fig. G.15 | Valutare le espressioni con il debugger. 5. Modificare i valori. Potete modificare i valori delle variabili durante l'esecuzione del programma nel debugger Ci pu essere utile per sperimentare diversi valori e per individuare gli errori logici. Potete utilizzare il comando set del debugger per modificare il valore di una variabile. Digitate set number1 = 90 per modificare il valore di number1, poi digitate print number1 per visualizzare il suo nuovo valore (Figura G.16).
(gdb) set number1 = 90 (gdb) print number1 $3 = 90 (gdb)

Fig. G.16 | Impostare il valore di una variabile mentre si in break mode. 6. Visualizzare il risultato del programma. Digitate continue per continuare l'esecuzione del programma. La riga 19 della Figura G.1 viene eseguita, passando number1, number2 e number3 alla funzione maximum. La funzione main in seguito visualizzer il numero massimo. Si noti che il risultato 90 (Figura G.17). Ci dimostra che il passo precedente ha cambiato il valore di number1 dal valore 22 che avevate inserito a 90.
(gdb) continue Continuing. Max is 90 Program exited normally. (gdb)

Fig. G.17 | Usare una variabile modificata durante l'esecuzione del programma. 7. Utilizzare il comando quit. Usate il comando comando far in modo che il debugger termini.
(gdb) quit $ quit

per terminare la sessione di debugging (Fig. G.18). Questo

Fig. G.18 | Uscire dal debugger utilizzando il comando quit. In questa sezione avete utilizzato il comando print del debugger per valutare le espressioni aritmetiche e booleane. Avete anche imparato come utilizzare il comando set per modificare il valore di una variabile durante l'esecuzione del vostro programma.

G.4 Controllare l'esecuzione utilizzando i comandi step, finish e next


Talvolta avrete la necessit di eseguire un programma riga per riga per trovare e correggere gli errori. Percorrere una porzione del vostro programma in questo modo pu aiutarvi a verificare che il codice si una funzione venga eseguito correttamente. I comandi di questa sezione vi permetteranno di eseguire una funzione riga per riga, di eseguire tutti i suoi comandi in un colpo solo o di eseguirne soltanto i rimanenti (nel caso in cui abbiate gi eseguito alcuni comandi all'interno della funzione stessa).

Copyright (C) 2010 Apogeo

1. Far partire il debugger. Fate partire il debugger digitando gdb ./a.out. 2. Impostate un breakpoint. Digitate break 19 per impostare un breakpoint in corrispondenza della riga 19. 3. Eseguire il programma. Eseguite il programma digitando run, poi inserite 22, 85 e 17 al prompt. A questo punto il debugger indicher che il breakpoint stato raggiunto e visualizzer il codice in riga 19. In seguito il debugger effettuer una pausa ed aspetter che il prossimo comando venga inserito. 4. Usare il comando step. Il comando step eseguir il prossimo comando nel programma. Se il prossimo comando da eseguire una chiamata di funzione, il controllo verr trasferito alla funzione chiamata. Il comando step vi abilita ad entrare nella funzione ed a studiare i suoi singoli comandi. Per esempio, potete utilizzare i comandi print e set per visualizzare e modificare le variabili nella funzione. Digitate step per entrare nella funzione maximum (Figura G.1). Il debugger vi indicher che il passo stato completato e visualizzer il prossimo comando eseguibile (Figura G.19), ovvero in questo caso, la riga 28 di figH_01.c.
(gdb) step maximum (x=22, y=85, z=17) at figI_03.c:28 28 int max = x; (gdb)

Fig. G.19 | Using the step command to enter a function.

5. Utilizzare il comando finish. Dopo aver proceduto per step nella funzione maximum, digitate finish. Questo comando esegue i comandi rimanenti nella funzione e restituisce il controllo nel punto dove la funzione era stata richiamata. Il comando finish esegue i comandi rimanenti nella funzione maximum, poi effettua una pausa in riga 19 nel main (Figura G.20). Anche il valore restituito dalla funzione maximum viene visualizzato. Nel caso di funzioni lunghe, potreste voler dare un'occhiata a poche linee chiave di codice e poi continuare il debugging del codice del chiamante. Il comando finish utile nelle situazioni in cui non volete esaminare riga per riga il resto di una funzione.
(gdb) finish Run till exit from #0 maximum ( x = 22, y = 85, z = 17) at figH_01.c:28 0x0804842b in main() at figH_01.c:19 19 printf("Max is %d\n", maximum(number1, number2, number3)); Value returned is $1 = 85 (gdb)

Fig. G.20 | Utilizzare il comando


chiamante.

finish

per completare l'esecuzione di una funzione e ritornare alla funzione

6. Utilizzare il comando continue per continuare l'esecuzione. Inserite il comando continue per continuare l'esecuzione fino al completamento del programma. 7. Eseguire nuovamente il programma. I breakpoint persistono fino alla fine della sessione di debugging in cui sono stati definiti. Quindi il breakpoint che avete impostato nel passo 2 ancora attivo. Digitate run per eseguire il programma e inserite 22, 85 e 17 al prompt. Come nel passo 3, il programma gira fino al raggiungimento del breakpoint in riga 19, poi il debugger effettua una pausa ed attende il comando successivo (Figura G.21).
(gdb) run Starting program: /home/user/AppJ/a.out Enter three integers: 22 85 17 Breakpoint 1, main() at figH_01.c:19 19 printf("Max is %d\n", maximum(number1, number2, number3)); (gdb)

Fig. G.21 | Far ripartire il programma.

8. Usare il comando next. Digitate next. Questo comando si comporta come il comando step, tranne quanto il prossimo comando da eseguire contiene una chiamata di funzione. In questo caso, la funzione chiamata viene eseguita nella sua interezze ed il programma avanza fino alla prossima riga eseguibile dopo la chiamata di funzione (Figura G.22). Nel passo 4, il comando step entra nella funzione chiamata. In questo esempio il comando next esegue la funzione maximum e visualizza il massimo dei tre interi. Il debugger effettua poi una pausa in riga 21.

Copyright (C) 2010 Apogeo

(gdb) next Max is 85 21 return 0; /* indica che il programma terminato con successo */ (gdb)

Fig. G.22 | Utilizzare il comando next per eseguire una funzione nella sua interezza. 9. Utilizzare il comando quit. Usate il comando quit per terminare la sessione di debugging (Figura G.23). Durante l'esecuzione del programma questo comando provoca la sua immediata terminazione invece di eseguire i comandi rimanenti nel main.
(gdb) quit The program is running. Exit anyway? (y or n) y $

Fig. G.23 | Uscire dal debugger utilizzando il comando quit. In questa sezione avete usato i comandi step e finish del debugger richiamabili durante l'esecuzione del programma. Avete visto come il comando next permetta di portarsi oltre una chiamata di funzione. Avete imparato anche che il comando quit termina una sessione di debugging.

G.5 Il comando watch


Il comando watch informa il debugger di tenere sotto controllo un dato. Nel momento in cui l'elemento osservato sar sul punto di cambiare, il debugger vi informer. In questa sezione userete il comando watch per osservare come la variabile number1 venga modificata durante l'esecuzione. 1. Far partire il debugger. Fate partire il debugger digitando gdb ./a.out. 2. Impostare un breakpoint ed eseguire il programma. Digitate break 14 per impostare un breakpoint in corrispondenza della riga 14. In seguito eseguite il programma con il comando run. Il debugger ed il programma effettueranno una pausa in corrispondenza del breakpoint in riga 14 (Figura G.24).
(gdb) break 14 Breakpoint 1 at 0x80483e5: file figH_01.c, line 14. (gdb) run Starting program: /home/user/AppJ/a.out Breakpoint 1, main () at figH_01.c:14 14 printf("Enter three integers: "); (gdb)

Fig. G.24 | Eseguire il programma fino al raggiungimento del primo breakpoint. 3. Tenere sotto controllo un dato. Impostate un watch su number1 digitando watch number1 (Figura G.25). Questo watch viene etichettato come watchpoint 2 in quanto i watchpoint vengono etichettati per mezzo della stessa sequenza numerica utilizzata per i breakpoint. Potete impostare un watch su ogni variabile od elemento di una struttura dati che sia visibile al momento. Ogni volta che la variabile osservata cambier, il debugger entrer in break mode e vi informer che il valore cambiato.
(gdb) watch number1 Hardware watchpoint2: number1 (gdb)

Fig. G.25 | Impostare un watchpoint su una variabile.

4. Continuare l'esecuzione. Digitate continue per continuare l'esecuzione ed inserire tre interi al prompt. Il debugger vi informer che il valore di number1 cambiato ed entrer in break mode (Figura G.26). Il vecchio valore di number1 il suo valore prima dell'inizializzazione. Tale valore pu differire ogni volta che il programma viene eseguito. Questo valore imprevedibile (e spesso indesiderabile) dimostra perch in C importante inizializzare tutte le variabili prima che siano utilizzate.

Copyright (C) 2010 Apogeo

(gdb) continue Continuing. Enter three integers: 22 85 17 Hardware watchpoint 2: number1 Old value = -1208401328 New value = 22 0xb7e6c692 in _IO_vfscanf() from /lib/i686/cmov/libc.so.6 (gdb)

Fig. G.26 | Entrare in break mode quando una variabile viene modificata. 5. Continuare l'esecuzione. Digitate continue ed il programma terminer l'esecuzione della funzione main. Il debugger rimuover il watch su number1 in quanto number1 non sar pi visibile quando la funzione main terminer. La rimozione del watchpoint far s che il debugger entri in break mode. Digitate nuovamente continue per terminare l'esecuzione del programma (Figura G.27). 6. Far ripartire il debugger e resettare il watch sulla variabile. Digitate run per far ripartire il debugger. Impostate ancora una volta un watch su number1 digitando watch number1. Questo watchpoint viene etichettato come watchpoint 3. Digitate continue per continuare l'esecuzione (Figura G.28). 7. Eliminare il watch sul dato osservato. Supponiamo che vogliate osservare un dato soltanto per una parte dell'esecuzione di un programma. Potete rimuovere il watch del debugger sulla variabile number1 digitando delete 3 (Figura G.29). Digitate continue e il programma terminer l'esecuzione senza rientrare in break mode.
(gdb) continue Continuing. Max is 85 Watchpoint 2 is deleted because the program has left the block in which its expression is valid. 0xb7e4aab7 in exit() from /lib/i686/cmov/libc.so.6 (gdb) continue Continuing Program exited normally (gdb)

Fig. G.27 | Continuare fino alla fine del programma.


gdb) run Starting program: /home/users/AppJ/a.out Breakpoint 1, main () at figI_03.c:14 14 printf("Enter three integers: "); (gdb) watch number1 Hardware watchpoint 3: number1 (gdb) continue Continuing Hardware watchpoint 3: number1 Old value = -1208798640 New value = 22 0xb7e0b692 in _IO_vfscanf() from /lib/i686/cmov/libc.so.6 (gdb)

Fig. G.28 | Resettare il watch su un dato.


(gdb) delete 3 (gdb) continue Continuing. Max is 85 Program exited normally. (gdb)

Fig. G.29 | Rimuovere un watch.

In questa sezione avete utilizzato il comando watch per abilitare il debugger ad informarvi quando il valore di una variabile cambia. Avete utilizzato il comando delete per eliminare un watch su un dato prima della fine del programma.

Copyright (C) 2010 Apogeo

G.6 Conclusione
In questa appendice avete imparato come inserire ed eliminare i breakpoint nel debugger. I breakpoint vi permettono di effettuare delle pause durante l'esecuzione del programma in modo da esaminare i valori delle variabili con il comando print del debugger, che vi pu essere d'aiuto nell'individuare e correggere gli errori logici. Avete utilizzato il comando print per esaminare il valore di un'espressione ed il comando set per modificare il valore di una variabile. Avete anche imparato i comandi del debugger (inclusi step, finish e next) che possono essere utilizzati per determinare se una funzione venga eseguita correttamente. Avete imparato ad usare il comando watch per tener traccia dei membri delle strutture dati mentre sono visibili. Infine avete imparato come usare il comando info break per elencare tutti i breakpoint ed i watchpoint impostati per un programma ed il comando delete per rimuovere i singoli breakpoint e watchpoint.

Esercizi di autovalutazione
G.1 Completate gli spazi in ognuna delle seguenti frasi: a) Un breakpoint non pu essere impostato in corrispondenza di una __________. b) Potete esaminare il valore di un'espressione utilizzando il comando __________ del debugger. c) Potete modificare il valore di una variabile utilizzando il comando __________ del debugger. d) Durante il debugging il comando __________ esegue le istruzioni rimanenti della funzione corrente e restituisce il controllo del programma alla posizione in cui la funzione era stata richiamata. e) Il comando del debugger __________ si comporta come il comando step quando la prossima istruzione da eseguire non contiene una chiamata di funzione. f) Il comando watch del debugger vi permette di osservare tutti i cambiamenti a un __________.

G.2 Stabilite quali delle seguenti affermazioni sono vere e quali false. Nel caso siano false, spiegatene il motivo. a) Quando l'esecuzione del programma viene sospesa in corrispondenza di un breakpoint, la prossima istruzione da eseguire quella dopo il breakpoint. b) I watch possono essere rimossi utilizzando il comando remove del debugger. c) L'opzione -g del compilatore deve essere utilizzata quando si vuole compilare i programmi per il debugging.

Risposte agli esercizi di autovalutazione


G.1 a) riga non eseguibile. b) print. c) set. d) finish. e) next. f) dato.

G.2 a) Falso. Quando l'esecuzione del programma viene sospesa in corrispondenza di un breakpoint, il prossimo comando da eseguire il comando corrispondente al breakpoint. b) Falso. I watch possono essere rimossi utilizzando il comando delete del debugger. c) Vero.

Copyright (C) 2010 Apogeo