GNU Debugger o GDB: una potent eina de depuració de codi font per a programes Linux


Un depurador té un paper vital en qualsevol sistema de desenvolupament de programari. Ningú pot escriure un codi sense errors alhora. Durant el desenvolupament, s'estan produint errors i cal resoldre'ls per millorar-los. Un sistema de desenvolupament està incomplet sense un depurador. Tenint en compte la comunitat de desenvolupadors de codi obert, GNU Debugger és la seva millor opció. També s'utilitza per al desenvolupament de programari comercial en plataformes tipus UNIX.

GNU Debugger, també conegut com a gdb, ens permet colar-nos a través del codi mentre s'executa o el que un programa estava intentant fer en el moment abans de fallar. GDB bàsicament ens ajuda a fer quatre coses principals per detectar defectes en el codi font.

  1. Inicieu el programa, especificant arguments que poden afectar el comportament general.
  2. Atura el programa en condicions especificades.
  3. Examineu l'error o quan es va aturar el programa.
  4. Canvia el codi i experimenta amb el codi modificat de manera instantània.

Podem utilitzar gdb per depurar programes escrits en C i C++ sense gaire esforç. A partir d'ara, el suport per a altres llenguatges de programació com D, Modula-2, Fortran és parcial.

Com començar amb GNU Debugger o GDB

GDB s'invoca mitjançant l'ordre gdb. Quan s'emet gdb, mostra informació sobre la plataforma i us envia a l'indicador (gdb), tal com es mostra a continuació.

 gdb
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)

Escriviu help list per veure les diferents classes d'ordres disponibles dins de gdb. Escriviu help seguit d'un nom de classe per a una llista d'ordres d'aquesta classe. Escriviu help all per a la llista de totes les ordres. Les abreviatures de noms de comanda es permeten si són inequívoques. Per exemple, podeu escriure n en comptes d'escriure següent o c per a continuar i així successivament.

Les ordres gdb d'ús habitual es mostren a la taula següent. Aquestes ordres s'han d'utilitzar des de l'indicador d'ordres gdb (gdb).

Tingueu en compte la diferència entre les dues ordres step i next. La següent ordre no entra a la funció si la línia següent és una trucada de funció. Mentre que l'ordre step pot entrar a la funció interior i veure què hi passa.

Considereu el codi font següent.

// 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 depurar el fitxer de sortida, hem de compilar el mateix amb l'opció -g a gcc de la següent manera.

$ gcc -g sum.c -o sum

El fitxer de sortida sum es pot adjuntar a gdb mitjançant qualsevol de les dues maneres següents:

1. Especificant el fitxer de sortida com a argument per a gdb.

$ gdb sum

2. Execució del fitxer de sortida dins de gdb mitjançant l'ordre file.

$ gdb
(gdb) file sum

L'ordre list enumera les línies del fitxer de codi font i mou el punter. Per tant, la primera llista mostrarà les 10 primeres línies i la següent llista mostrarà les 10 següents i així successivament.

(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 iniciar l'execució, emet l'ordre executa. Ara el programa s'executa amb normalitat. Però ens hem oblidat de posar alguns punts d'interrupció al codi font per a la depuració, oi? Aquests punts d'interrupció es poden especificar per a funcions o en línies especificades.

(gdb) b main

Nota: he utilitzat una abreviatura b per a break.

Després d'establir el punt d'interrupció a la funció principal, tornar a executar el programa s'aturarà a la línia 11. El mateix es pot fer efectiu si el número de línia es coneix abans.

(gdb) b sum.c:11

Ara passeu per les línies de codi utilitzant l'ordre següent o n. És important tenir en compte que l'ordre següent no entra dins del codi de funció tret que s'estableixi un punt d'interrupció a la funció. Provem ara l'ordre print. Estableix el punt de ruptura a la suma de la funció com a continuació.

(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]

Si el programa que s'està executant requereix paràmetres de línia d'ordres, proporcioneu els mateixos juntament amb l'ordre executa com.

(gdb) run   . . .

Els fitxers de biblioteca compartida associats amb el programa en execució actual es poden llistar com a.

(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

GDB també és capaç de modificar variables al llarg de l'execució del programa. Provem-ho. Com s'ha esmentat anteriorment, establiu el punt d'interrupció a la línia 16 i executeu el programa.

(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

Ara a = 1, b = 2 i el resultat hauria de ser z = 3. Però aquí hem canviat el resultat final a z = 4 a la funció principal. D'aquesta manera la depuració es pot fer més fàcil amb gdb.

Per obtenir la llista de tots els punts d'interrupció, escriviu punts d'interrupció d'informació.

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

Aquí només hi ha un punt de trencament i és To. activat desactiva els punts d'interrupció especifiqueu el número de punt d'interrupció juntament amb l'ordre desactivar. Per activar després, utilitzeu l'ordre activa.

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

També podeu suprimir els punts d'interrupció amb l'ordre suprimeix.

S'estan executant nombrosos processos en segon pla en un sistema GNU/Linux. Per depurar un procés en execució primer de tot, hem de trobar l'identificador de procés d'aquest procés en particular. L'ordre pidof us proporciona el pid d'un procés.

$ pidof <process_name>

Ara hem d'adjuntar aquest pid a gdb. Hi ha 2 maneres.

1. Especificant pid juntament amb gdb.

$ gdb -p <pid>

2. Utilitzant l'ordre attach de gdb.

(gdb) attach <pid>

Això és tot per ara. Aquests són només conceptes bàsics de gdb per començar bé a depurar el codi font i és molt més que les coses explicades anteriorment. Per exemple, podem depurar utilitzant la informació de la pila, les variables d'entorn i molt més. Intenta jugar amb totes aquestes coses...