GNU Debugger o GDB: una poderosa herramienta de depuración de código fuente para programas Linux


Un depurador juega un papel vital en cualquier sistema de desarrollo de software. Nadie puede escribir un código sin errores de una sola vez. Durante el curso del desarrollo, se están generando errores y deben resolverse para mejorar aún más. Un sistema de desarrollo está incompleto sin un depurador. Teniendo en cuenta la comunidad de desarrolladores de código abierto, GNU Debugger es su mejor opción. También se utiliza para el desarrollo de software comercial en plataformas de tipo UNIX.

GNU Debugger, también conocido como gdb, nos permite escabullirse por el código mientras se ejecuta o lo que un programa estaba tratando de hacer en el momento antes de fallar. GDB básicamente nos ayuda a hacer cuatro cosas principales para detectar fallas en el código fuente.

  1. Start the program, specifying arguments that may affect the general behavior.
  2. Stop the program on specified conditions.
  3. Examine the crash or when program was stopped.
  4. Change the code and to experiment with the modified code instantaneously.

Podemos usar gdb para depurar programas escritos en C y C ++ sin mucho esfuerzo. A partir de ahora, el soporte para otros lenguajes de programación como D, Modula-2, Fortran es parcial.

Empezando con GNU Debugger o GDB

GDB se invoca mediante el comando gdb . Al emitir gdb , muestra información sobre la plataforma y lo lleva al indicador ( gdb ) como se muestra a continuación.

[[email protected] ~]# 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)

Escriba help list para conocer las diferentes clases de comandos disponibles dentro de gdb. Escriba ayuda seguido de un nombre de clase para obtener una lista de comandos en esa clase. Escriba ayudar a todos para ver la lista de todos los comandos. Se permiten las abreviaturas de los nombres de los comandos si no son ambiguas. Por ejemplo, puede escribir n en lugar de escribir siguiente o c para continuar y así sucesivamente.

Los comandos gdb más utilizados se enumeran en la siguiente tabla. Estos comandos deben usarse desde el símbolo del sistema de gdb ( gdb ).

Note la diferencia entre los dos comandos paso y siguiente . El siguiente comando no entra en la función si la siguiente línea es una llamada de función. Mientras que el comando paso puede ingresar a la función y ver qué sucede allí.

Considere el siguiente código fuente.

// 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; 
}

Para depurar el archivo de salida, necesitamos compilar lo mismo con la opción -g en gcc de la siguiente manera.

$ gcc -g sum.c -o sum

El archivo de salida sum se puede adjuntar a gdb a través de cualquiera de las siguientes 2 formas:

1. Especificando el archivo de salida como argumento para gdb.

$ gdb sum

2. Ejecutando el archivo de salida dentro de gdb usando el comando file .

$ gdb
(gdb) file sum

El comando list enumera las líneas en el archivo de código fuente y mueve el puntero. Entonces, la primera lista mostrará las primeras 10 líneas y la siguiente lista mostrará las siguientes 10 y así sucesivamente.

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

Para iniciar la ejecución, ejecute el comando ejecutar . Ahora el programa se ejecuta normalmente. Pero nos olvidamos de poner algunos puntos de interrupción en el código fuente para la depuración, ¿verdad? Estos puntos de interrupción se pueden especificar para funciones o en líneas específicas.

(gdb) b main

Nota: he utilizado una abreviatura b para romper.

Después de establecer el punto de interrupción en la función principal, volver a ejecutar el programa se detendrá en la línea 11. Se puede hacer lo mismo si se conoce el número de línea antes.

(gdb) b sum.c:11

Ahora recorra las líneas de código usando el comando next o n . Es importante tener en cuenta que el comando next no entra en el código de la función a menos que se establezca un punto de interrupción en la función. Probemos ahora el comando imprimir . Establezca el punto de interrupción en la suma de funciones como se muestra a continuación.

(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 se está ejecutando requiere parámetros de línea de comandos, proporcione los mismos junto con el comando ejecutar que.

(gdb) run   . . .

Los archivos de biblioteca compartida asociados con el programa en ejecución actual se pueden enumerar como.

(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 también es capaz de modificar variables durante la ejecución del programa. Probemos esto. Como se mencionó anteriormente, establezca el punto de interrupción en la línea 16 y ejecute 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

Ahora a u003d 1, b u003d 2 y el resultado debería ser z u003d 3. Pero aquí cambiamos el resultado final a z u003d 4 en la función principal. De esta manera, la depuración se puede hacer más fácil usando gdb.

Para obtener la lista de todos los puntos de interrupción, escriba info breakpoints .

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

Aquí solo hay un punto de ruptura y es To. habilitado deshabilitar los puntos de interrupción especifique el número de punto de interrupción junto con el comando deshabilitar . Para habilitarlo luego use el 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

También puede eliminar los puntos de interrupción con el comando eliminar .

Numerosos procesos se ejecutan en segundo plano en un sistema GNU/Linux. Para depurar un proceso en ejecución, en primer lugar, debemos encontrar la identificación del proceso de ese proceso en particular. El comando pidof le da el pid de un proceso.

$ pidof <process_name>

Ahora necesitamos adjuntar este pid a gdb. Hay dos formas.

1. Especificando pid junto con gdb.

$ gdb -p <pid>

2. Usando el comando adjuntar desde gdb.

(gdb) attach <pid>

Eso es todo por ahora. Estos son solo los conceptos básicos de gdb para comenzar bien en la depuración del código fuente y es mucho más que lo explicado anteriormente. Por ejemplo, podemos depurar usando la información de la pila, las variables de entorno y mucho más. Intenta jugar con todas estas cosas ...