Independientemente de la experiencia que tenga como codificador, cualquier software que desarrolle no puede estar completamente libre de errores. Por lo tanto, identificar errores y corregirlos es una de las tareas más importantes en el ciclo de desarrollo de software. Si bien hay muchas formas de identificar errores (pruebas, auto revisión del código y más), hay un software dedicado, llamado depurador, que lo ayuda a comprender exactamente dónde está el problema, para que pueda solucionarlo fácilmente.
Si es un programador de C/C++ o desarrolla software utilizando los lenguajes de programación Fortran y Modula-2, le alegrará saber que existe un excelente depurador, denominado GDB, que le permite depurar fácilmente su código en busca de errores y otros problemas. En este artículo, discutiremos los conceptos básicos de GDB, incluidas algunas de las funciones/opciones útiles que ofrece.
Pero antes de continuar, vale la pena mencionar que todas las instrucciones y los ejemplos que se presentan en este artículo se probaron en Ubuntu 14.04LTS. El código de ejemplo utilizado en el tutorial está escrito en lenguaje C; el shell de la línea de comandos que hemos usado es bash (versión 4.3.11); y la versión de GDB que hemos usado es 7.7.1.
Conceptos básicos del depurador GDB
En términos sencillos, GDB le permite echar un vistazo dentro de un programa mientras se ejecuta, algo que le permite ayudar a identificar dónde está exactamente el problema. Discutiremos el uso del depurador GDB a través de un ejemplo de trabajo en la siguiente sección, pero antes de eso, aquí, discutiremos algunos puntos básicos que lo ayudarán más adelante.
En primer lugar, para utilizar con éxito depuradores como GDB, debe compilar su programa de tal manera que el compilador también produzca información de depuración que requieren los depuradores. Por ejemplo, en el caso del compilador gcc, que usaremos para compilar el programa C de ejemplo más adelante en este tutorial, debe usar -g opción de línea de comando mientras compila su código.
Para saber qué dice la página del manual del compilador gcc sobre esta opción de línea de comando, diríjase aquí.
El siguiente paso es asegurarse de que tiene GDB instalado en su sistema. Si ese no es el caso, y está en un sistema basado en Debian como Ubuntu, puede instalar fácilmente la herramienta usando el siguiente comando:
sudo apt-get install gdb
Para la instalación en cualquier otra distribución, dirígete aquí.
Ahora, una vez que haya compilado su programa de manera que esté listo para la depuración, y GDB esté allí en su sistema, puede ejecutar su programa en modo de depuración usando el siguiente comando:
gdb [prog-executable-name]
Si bien esto iniciará el depurador de GDB, el ejecutable de su programa no se iniciará en este punto. Este es el momento en el que puede definir la configuración relacionada con la depuración. Por ejemplo, puede definir un punto de interrupción que le indique a GDB que pause la ejecución del programa en un número de línea o función en particular.
Continuando, para iniciar su programa, deberá ejecutar el siguiente comando gdb:
run
Vale la pena mencionar aquí que si su programa requiere que se le pasen algunos argumentos de línea de comando, puede especificarlos aquí. Por ejemplo:
run [arguments]
GDB proporciona muchos comandos útiles que son útiles durante la depuración. Discutiremos algunos de ellos en el ejemplo de la siguiente sección.
Ejemplo de uso de GDB
Ahora tenemos una idea básica sobre GDB y su uso. Así que tomemos un ejemplo y apliquemos el conocimiento allí. Aquí hay un código de ejemplo:
#include <stdio.h>
int main()
{
int out = 0, tot = 0, cnt = 0;
int val[] = {5, 54, 76, 91, 35, 27, 45, 15, 99, 0};
while(cnt < 10)
{
out = val[cnt];
tot = tot + 0xffffffff/out;
cnt++;
}
printf("\n Total = [%d]\n", tot);
return 0;
}
Básicamente, lo que hace este código es elegir cada valor contenido en la matriz 'val', lo asigna al entero 'out' y luego calcula 'tot' sumando el valor anterior de la variable y el resultado de '0xffffffff/ fuera.'
El problema aquí es que cuando se ejecuta el código, produce el siguiente error:
$ ./gdb-test
Floating point exception (core dumped)
Entonces, para depurar el código, el primer paso sería compilar el programa con -g. Aquí está el comando:
gcc -g -Wall gdb-test.c -o gdb-test
A continuación, ejecutemos GDB y hagámosle saber qué ejecutable queremos depurar. Aquí está el comando para eso:
gdb ./gdb-test
Ahora, el error que obtengo es 'excepción de punto flotante' y, como la mayoría de ustedes ya sabrán, es causado por n % x, cuando x es 0. Entonces, con eso en mente, puse un punto de ruptura en el número de línea 11, donde se está realizando la división. Esto se hizo de la siguiente manera:
(gdb) break 11
Tenga en cuenta que '(gdb)' es el aviso del depurador, acabo de escribir el comando 'romper'.
Ahora, le pedí a GDB que iniciara la ejecución del programa:
run
Entonces, cuando se alcanzó el punto de interrupción por primera vez, esto es lo que mostró GDB en el resultado:
Breakpoint 1, main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
(gdb)
Como puede ver en el resultado anterior, el depurador mostró la línea donde se colocó el punto de interrupción. Ahora, imprimamos el valor actual de 'out'. Esto se puede hacer de la siguiente manera:
(gdb) print out
$1 = 5
(gdb)
Como puede ver, se imprimió el valor '5'. Entonces, las cosas están bien en este momento. Le pedí al depurador que continuara con la ejecución del programa hasta el siguiente punto de interrupción, algo que se puede hacer usando el comando 'c'.
c
Seguí haciendo este trabajo, hasta que vi que el valor de 'fuera' era cero.
...
...
...
Breakpoint 1, main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
(gdb) print out
$2 = 99
(gdb) c
Continuing.
Breakpoint 1, main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
(gdb) print out
$3 = 0
(gdb)
Ahora, para confirmar que este es el problema exacto, usé el comando 's' (o 'paso') de GDB en lugar de 'c' esta vez. La razón es que solo quería la línea 11, donde la ejecución del programa está actualmente en pausa, para ejecutar y ver si se produce un bloqueo en este punto.
Esto es lo que sucedió:
(gdb) s
Program received signal SIGFPE, Arithmetic exception.
0x080484aa in main () at gdb-test.c:11
11 tot = tot + 0xffffffff/out;
Sí, como lo confirma el resultado resaltado arriba, aquí es donde se lanzó la excepción. La confirmación final llegó cuando intenté ejecutar el comando 's' una vez más:
(gdb) s
Program terminated with signal SIGFPE, Arithmetic exception.
The program no longer exists.
De esta manera, puede depurar sus programas usando GDB.
Conclusión
Acabamos de arañar la superficie aquí, ya que GDB ofrece muchas funciones para que los usuarios exploren y usen. Vaya a la página de manual de GDB para obtener más información sobre la herramienta e intente usarla cada vez que esté depurando algo en su código. El depurador tiene un poco de curva de aprendizaje asociada, pero vale la pena el trabajo duro.