02. Depuración: breakpoints I

Publicado por

En la nota anterior, a modo de introducción, mostré a grandes rasgos el uso básico del depurador de GNU. Bien, ha llegado el momento de entrar un poco más en detalles.

Gracias a que compilamos nuestro programa incluyendo información extra (los símbolos de depuración); GDB en este caso nos proyecta la ilusión de ejecutar el programa línea por línea, en lugar de instrucción por instrucción, que es como realmente lo ejecuta la computadora.

En principio, el depurador se encarga de ejecutar el programa que queremos revisar, de la misma forma que lo haríamos nosotros. No es sino hasta que el depurador nos permite manipular la ejecución del programa, que podemos percibir el potencial de este tipo de herramientas ¿cómo manipulamos la ejecución del programa?

GDB nos proporciona tres mecanismos para detener la ejecución de nuestro programa: breakpoints, whatchpoints y catchpoints. Por ahora, hablaremos de los primeros.

Breakpoints

Un punto de quiebre, es una marca en algún lugar del programa, cuando la ejecución del programa alcanza el lugar marcado por el breakpoint el programa es pausado. En este contexto, el término «lugar» puede referirse a una línea dentro del archivo fuente actual u otro módulo, o al nombre de una función. La forma de marcar un lugar con un breakpoint es a través del comando break seguido por el lugar que será marcado por el punto de quiebre. Para ilustrar el uso básico de estos, utilizaré el programa de ejemplo mostrado en la nota anterior.

➜ gcc -g pila.c -o pila
➜ gdb pila
# ... Salida omitida
(gdb) break 19
Breakpoint 1 at 0x4005a5: file pila.c, line 19.
(gdb) break print
Breakpoint 2 at 0x40069b: file pila.c, line 46.
(gdb)

Si quieres establecer el punto de quiebre en algún lugar de un módulo diferente, hay que hacerlo de la siguiente manera:

(gdb) break pila.c:19
Breakpoint 1 at 0x4005a5: file pila.c, line 19.
(gdb) break pila.c:print
Breakpoint 2 at 0x40069b: file pila.c, line 46.
(gdb)

Comúnmente es necesario establecer varios breakpoints en un programa, por lo que será necesario consultar en dónde están marcados. Esta información es proporcionada por el comando info utilizado de la siguiente manera:

(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004005a5 in main at pila.c:19
2       breakpoint     keep y   0x000000000040069b in print at pila.c:46
(gdb)

La salida de este comando tiene la siguiente estructura:

  • Identificador: un número único con el cual podemos identificar rápidamente el breakpoint.
  • Tipo: indica si el punto de quiebre es un breakpoint, whatchpoint o un catchpoint.
  • Disposición: este valor se utiliza para decidir qué sucederá en caso de que el programa pause su ejecución.
  • Estado: indica si el punto de quiebre está habilitado o no.
  • Dirección: cada breakpoint está asociado a un lugar determinado, este valor refleja la ubicación del punto de quiebre, en términos de dirección de memoria.
  • Ubicación: este valor se refiere a la ubicación del punto de quiebre a un nivel más alto, es decir en términos de líneas de código, nombres de función, etcétera.

Una vez que hayamos terminado de examinar el estado del programa, podemos reanudar la ejecución del programa; ya sea, avanzando una sola línea, a través del comando next o de una vez ejecutar el programa normalmente utilizando el comando continue; en caso de que el flujo del programa encuentre otro punto de quiebre, la ejecución se pausará nuevamente, dando la oportunidad de examinar el estado del programa.

(gdb) break 19
Breakpoint 1 at 0x4005a5: file pila.c, line 19.
(gdb) break print
Breakpoint 2 at 0x40069b: file pila.c, line 46.
(gdb) run 5 4 3 2 1
Starting program: /home/user/bin/pila 5 4 3 2 1

Breakpoint 1, main (argc=6, argv=0x7fffffffe198) at pila.c:19
19    PILA_LIMPIAR(numeros);
(gdb) next
21    while (*++argv)
(gdb) next
22      push(&numeros, atoi(*argv));
(gdb) continue
Continuing.

Breakpoint 2, print (p=0x7fffffffe090) at pila.c:46
46    int t = p->tope;
(gdb)

Cuando ya no necesites más uno de estos breakpoints; puedes simplemente eliminarlo utilizando el comando delete.

(gdb) delete 1
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x000000000040069b in print at pila.c:46
(gdb)

También es posible deshabilitar el punto de quiebre y volver a habilitarlo cuando sea necesario, a través de los comandos disable y enable.

(gdb) disable 2
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
2       breakpoint     keep n   0x000000000040069b in print at pila.c:46
(gdb) enable 2
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x000000000040069b in print at pila.c:46
(gdb)

Espero que esta nota te sea de utilidad para explotar esta útil herramienta GDB. En las siguientes entregas de esta serie, continuaré explicando el resto de los mecanismos disponibles para controlar la ejecución del programa. Hasta entonces.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *