A debugger plays a vital role in any software development system. Nobody can write a bug-free code all at once. During the course of development, bugs are being raised and needs to be solved for further enhancement. A development system is incomplete without a debugger. Considering the open source developers community, GNU Debugger is their best choice. It is also used for commercial software development on UNIX type platforms.

Il GNU Debugger, conosciuto anche come gdb, ci consente di esaminare il codice mentre viene eseguito o cosa stava tentando di fare un programma nel momento prima di bloccarsi. GDB in sostanza ci aiuta a fare quattro cose principali per individuare difetti nel codice sorgente.
- Avviare il programma, specificando gli argomenti che potrebbero influenzare il comportamento generale.
- Fermare il programma in determinate condizioni.
- Esaminare il crash o il momento in cui il programma è stato interrotto.
- Modificare il codice ed eseguire esperimenti con il codice modificato istantaneamente.
Possiamo utilizzare gdb per eseguire il debug di programmi scritti in C e C++ senza troppa fatica. Al momento il supporto ad altri linguaggi di programmazione come D, Modula-2, Fortran è parziale.
Iniziare con GNU Debugger o GDB
GDB viene invocato utilizzando il comando gdb. Emettendo il comando gdb, vengono visualizzate alcune informazioni sulla piattaforma e si viene inseriti nel prompt (gdb) come mostrato di seguito.
[root@fedora20 ~]# gdb
Output di Esempio
GNU gdb (GDB) Fedora 7.6.50.20130731-19.fc20 Copyright (C) 2013 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 "x86_64-redhat-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word". (gdb)
Digitare aiuto per elencare le diverse classi di comandi disponibili all’interno di gdb. Digitare help seguito da un nome di classe per ottenere un elenco dei comandi in quella classe. Digitare help all per l’elenco di tutti i comandi. Le abbreviazioni dei nomi dei comandi sono ammesse se sono non ambigue. Ad esempio, è possibile digitare n invece di digitare next o c per continua e così via.
Comandi GDB più comunemente usati
I comandi gdb più comunemente usati sono elencati nella seguente tabella. Questi comandi devono essere utilizzati dal prompt dei comandi di gdb (gdb).
Command
|
Description
|
run
|
Start a program execution
|
quit
|
Quit gdb
|
print expr
|
Print expression where expr may be a variable name too
|
next
|
Go to next line
|
step
|
Step into next line
|
continue
|
Continue from the current line till the end of program or next break point
|
Nota la differenza tra i due comandi step e next. Il comando next non entra all’interno di una funzione se la linea successiva è una chiamata di funzione. Mentre il comando step può entrare all’interno della funzione e vedere cosa succede lì.
A sample session with GDB
Considera il seguente codice sorgente.
// sum.c #include <stdio.h> int sum (int a, int b) { int c; c = a + b; return c; } int main() { int x, y, z; printf("\nEnter the first number: "); scanf("%d", &x); printf("Enter the second number: "); scanf("%d", &y); z = sum (x, y); printf("The sum is %d\n\n", z); return 0; }
Per poter eseguire il debug del file di output dobbiamo compilarlo con l’opzione -g al gcc come segue.
$ gcc -g sum.c -o sum
Il file di output sum può essere associato a gdb tramite uno dei seguenti 2 modi:
1. Specificando il file di output come argomento per gdb.
$ gdb sum
2. Eseguendo il file di output all’interno di gdb utilizzando il comando file.
$ gdb (gdb) file sum
Il comando list elenca le linee nel file del codice sorgente e sposta il puntatore. Quindi prima list mostrerà le prime 10 linee e poi list mostrerà le successive 10 e così via.
(gdb) list 1 #include <stdio.h> 2 3 int sum (int a, int b) { 4 int c; 5 c = a + b; 6 return c; 7 } 8 9 int main() { 10 int x, y, z;
Per avviare l’esecuzione, emetti il comando run . Ora il programma viene eseguito normalmente. Ma ci siamo dimenticati di impostare dei punti di interruzione nel codice sorgente per il debug, giusto? Questi punti di interruzione possono essere specificati per funzioni o a linee specifiche.
(gdb) b main
Nota: Ho utilizzato l’abbreviazione b per break.
Dopo aver impostato un punto di interruzione nella funzione principale, il riprocessamento del programma si fermerà alla riga 11. La stessa cosa può essere ottenuta se si conosce il numero di linea in precedenza.
(gdb) b sum.c:11
Ora passa attraverso le righe di codice utilizzando il comando next o n. È importante notare che il comando next non entra nel codice della funzione a meno che non venga impostato un punto di interruzione sulla funzione. Proviamo ora il comando print. Imposta un punto di interruzione sulla funzione “sum” come segue.
(gdb) b sum Breakpoint 1 at 0x4005aa: file sum.c, line 5. (gdb) r Starting program: /root/sum Enter the first number: 2 Enter the second number: 3 Breakpoint 1, sum (a=2, b=3) at sum.c:5 5 c = a + b; (gdb) p a $1 = 2 (gdb) p b $2 = 3 (gdb) c Continuing. The sum is 5 [Inferior 1 (process 3444) exited normally]
Se il programma in esecuzione richiede parametri da riga di comando, forniscili insieme al comando run come segue.
(gdb) run . . .
I file di libreria condivisa associati al programma in esecuzione possono essere elencati come segue.
(gdb) info share From To Syms Read Shared Object Library 0x00000035a6000b10 0x00000035a6019c70 Yes /lib64/ld-linux-x86-64.so.2 0x00000035a641f560 0x00000035a6560bb4 Yes /lib64/libc.so.6
Modifica delle variabili
GDB è anche in grado di modificare le variabili durante l’esecuzione del programma. Proviamo questo. Come accennato in precedenza, impostare un punto di interruzione alla riga 16 e avviare il programma.
(gdb) r Starting program: /root/sum Enter the first number: 1 Enter the second number: 2 Breakpoint 1, main ( ) at sum.c:16 16 printf("The sum is %d\n\n", z); (gdb) set z=4 (gdb) c Continuing. The sum is 4
Ora a = 1, b = 2 e il risultato dovrebbe essere z = 3. Ma qui abbiamo cambiato il risultato finale in z = 4 nella funzione principale. In questo modo il debug può essere reso più facile utilizzando gdb.
Abilita/Disabilita i punti di interruzione
Per ottenere l’elenco di tutti i punti di interruzione, digitare info breakpoints.
(gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004005c2 in main at sum.c:11
Qui c’è solo un punto di interruzione ed è abilitato. Per disabilitare i punti di interruzione, specificare il numero del punto di interruzione insieme al comando disable. Per abilitarli successivamente, utilizzare il comando enable.
(gdb) disable 1 (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep n 0x00000000004005c2 in main at sum.c:11
Puoi anche eliminare i punti di interruzione con il comando delete.
Debug dei processi in esecuzione
In un sistema GNU/Linux sono in esecuzione numerosi processi in background. Per eseguire il debug di un processo in esecuzione, prima di tutto dobbiamo trovare l’ID del processo in questione. Il comandopidof ti fornisce l’ID del processo.
$ pidof <process_name>
Ora dobbiamo collegare questo PID a gdb. Ci sono 2 modi.
1. Specificando il PID insieme a gdb.
$ gdb -p <pid>
2. Utilizzando il comando attach da gdb.
(gdb) attach <pid>
E questo è tutto per ora. Questi sono solo concetti di base di gdb per iniziare bene nel debug del codice sorgente ed è molto di più rispetto alle cose spiegate sopra. Ad esempio, possiamo eseguire il debug utilizzando le informazioni dello stack, le variabili d’ambiente e molto altro. Prova a sperimentare con tutte queste cose…
Source:
https://www.tecmint.com/debug-source-code-in-linux-using-gdb/