Ricerca nel sito web

GNU Debugger o GDB: un potente strumento di debug del codice sorgente per programmi Linux


Un debugger svolge un ruolo vitale in qualsiasi sistema di sviluppo software. Nessuno può scrivere un codice privo di bug tutto in una volta. Nel corso dello sviluppo vengono segnalati bug che devono essere risolti per ulteriori miglioramenti. Un sistema di sviluppo è incompleto senza un debugger. Considerando la comunità di sviluppatori open source, GNU Debugger è la scelta migliore. Viene utilizzato anche per lo sviluppo di software commerciale su piattaforme di tipo UNIX.

GNU Debugger, noto anche come gdb, ci consente di intrufolarci nel codice mentre viene eseguito o in ciò che un programma stava cercando di fare in un momento prima che si bloccasse. GDB fondamentalmente ci aiuta a fare quattro cose principali per individuare i difetti nel codice sorgente.

  1. Avviare il programma, specificando gli argomenti che possono influenzare il comportamento generale.
  2. Interrompere il programma alle condizioni specificate.
  3. Esaminare l'arresto anomalo o il momento in cui il programma è stato interrotto.
  4. Cambia il codice e sperimenta istantaneamente il codice modificato.

Possiamo usare gdb per eseguire il debug di programmi scritti in C e C++ senza troppi sforzi. Al momento il supporto per altri linguaggi di programmazione come D, Modula-2, Fortran è parziale.

Iniziare con GNU Debugger o GDB

GDB viene richiamato utilizzando il comando gdb. All'emissione di gdb, mostra alcune informazioni sulla piattaforma e ti porta al prompt (gdb) come mostrato di seguito .

[root@fedora20 ~]# gdb
Uscita del campione
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)

Digita help list per visualizzare le diverse classi di comandi disponibili all'interno di gdb. Digita help seguito dal nome di una classe per un elenco di comandi in quella classe. Digita help all per l'elenco di tutti i comandi. Le abbreviazioni dei nomi di comando sono consentite se non ambigue. Ad esempio, puoi digitare n invece di digitare successivo o c per continua e così via.

Comandi GDB più comunemente usati

I comandi gdb più comunemente utilizzati sono elencati nella tabella seguente. Questi comandi devono essere utilizzati dal prompt dei comandi di gdb (gdb).

Command

Descrizione

run

Avvia l'esecuzione di un programma

quit

Esci da gdb

print expr

Stampa espressione dove expr può essere anche un nome di variabile

next

Vai alla riga successiva

step

Passa alla riga successiva

continue

Continua dalla riga corrente fino alla fine del programma o al punto di interruzione successivo

Nota la differenza tra i due comandi passaggio e successivo. Il comando successivo non va all'interno della funzione se la riga successiva è una chiamata di funzione. Mentre il comando step può entrare nella funzione interna e vedere cosa succede lì.

Una sessione di esempio con 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 eseguire il debug del file di output dobbiamo compilare lo stesso con l'opzione -g in gcc come segue.

gcc -g sum.c -o sum

Il file di output sum può essere allegato a gdb in uno dei due modi seguenti:

1. Specificando il file di output come argomento per gdb.

gdb sum

2. Esecuzione del file di output all'interno di gdb utilizzando il comando file.

gdb
(gdb) file sum

Il comando list elenca le righe nel file del codice sorgente e sposta il puntatore. Quindi il primo elencovisualizzerà le prime 10 righe e il successivo elenco 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, esegui il comando esegui. Ora il programma viene eseguito normalmente. Ma ci siamo dimenticati di inserire alcuni punti di interruzione nel codice sorgente per il debug, giusto? Questi punti di interruzione possono essere specificati per funzioni o su righe specificate.

(gdb) b main

Nota: ho utilizzato l'abbreviazione b per break.

Dopo aver impostato il punto di interruzione nella funzione principale, la riesecuzione del programma si fermerà alla riga 11. La stessa cosa può essere resa effettiva se il numero di riga è noto in precedenza.

(gdb) b sum.c:11

Ora scorri le righe del codice utilizzando il comando next o n. È importante notare che il comando successivo non entra nel codice della funzione a meno che non sia impostato un punto di interruzione sulla funzione. Proviamo ora il comando stampa. Impostare il punto di interruzione sulla somma delle funzioni come di seguito.

(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 della riga di comando, fornisci gli stessi insieme al comando esegui come.

(gdb) run   . . .

I file della libreria condivisa associati al programma attualmente in esecuzione possono essere elencati come.

(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. Proviamolo. Come accennato in precedenza, imposta il punto di interruzione alla riga 16 ed esegui 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 inz=4 nella funzione principale. In questo modo il debug può essere reso più semplice utilizzando gdb.

Abilita/Disabilita punti di interruzione

Per ottenere l'elenco di tutti i punti di interruzione, digita info breakpoint.

(gdb) info breakpoints 
Num     Type           Disp Enb Address            What 
1       breakpoint     keep y   0x00000000004005c2 in main at sum.c:11

Qui c'è un solo punto di interruzione ed è To. abilitato disabilita i punti di interruzione specifica il numero del punto di interruzione insieme al comando disabilita. Per abilitarlo successivamente, utilizza il comando abilita.

(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 elimina.

Debug dei processi in esecuzione

In un sistema GNU/Linux vengono eseguiti in background numerosi processi. Per eseguire il debug di un processo in esecuzione dobbiamo prima trovare l'ID di quel particolare processo. Il comando pidofti dà il pid di un processo.

pidof <process_name>

Ora dobbiamo allegare questo pid a gdb. Ci sono 2 modi.

1. Specificando pid insieme a gdb.

gdb -p <pid>

2. Utilizzando il comando attach da gdb.

(gdb) attach <pid>

È tutto per ora. Queste sono solo le basi di gdb per iniziare bene il debug del codice sorgente e sono molto più delle cose spiegate sopra. Ad esempio, possiamo eseguire il debug utilizzando le informazioni sullo stack, le variabili di ambiente e molto altro. Prova a giocare con tutte queste cose...