gdb-ascii-logo-800px
Image Source: Make Tech Easier Image link 

Para crear software de buena calidad debemos contar con los métodos y las herramientas adecuadas. En esa oportunidad quiero compartir un corto resumen (y al final de este artículo algunos recursos) que nos ayudarán con la depuración de nuestro software. GNU Debugger o GDB es una potente herramienta que nos ayudará a detectar errores y corregirlos, siendo por lo tanto una herramienta casi imprescindible para todo programador de C/C++ y otros lenguajes (soportados), en los que se quiera producir software de calidad.

GDB es una herramienta que nos ha acompañado desde los inicios de la informática, y por lo tanto es de esperarse que como muchas otras de la misma familia (gcc, g++, etc), fueron pensadas para funcionar en la terminal (así es, existe desde aquella época en la que no existían las interfaces de ventanas o GUIs). Aunque en la actualidad existen muchos frontends (GUIs) normalmente no resultan tan necesarios, una vez has aprendido a manejarte en la depuración desde consola. Por esta razón, en este manual (su primera versión) se ha dedicado a reunir la información necesaria para que inicies tu aprendizaje de GDB y posteriormente amplíes tus conocimientos sobre el mismo, al tiempo que tendrás el criterio para que elijas alguna interfaz de usuario si la consideras necesaria.

 


Iniciando una sesión de depuración

En primer lugar, para iniciar una sesión de depuración de una aplicación específica, debemos realizar la compilación indicando al compilador que agregue los símbolos de depuración para necesarios para gdb.

Agregar símbolos de depuración a los ejecutables

[g++|gcc]   -ggdb   -o 

Donde <sources> hace referencia a los archivos de código fuente (que se desean compilar) y <output> hace referencia al nombre del programa resultante (entregado por el compilador).

Una vez hemos compilado nuestra aplicación con la opción -ggdb podemos ejecutar la siguiente línea en la terminal de comandos (nota: estar ubicado en el mismo directorio del ejecutable):

gdb program_name

La línea anterior inicia la sesión de depuración con gdb. Para iniciar la ejecución/depuración de la aplicación ejecutamos el comando start, entonces el programa analizado se detendrá al inicio de la función main(…).


Atajos de teclado

  • CTRL+X+A: (Habilita o deshabilita) la visualización del código fuente en pantalla dividida.
  • CTRL+X+2: Lanza una segunda ventana (assembly) y permite moverse entre ellas.
  • CTRL+C: Como en cualquier otra aplicación en Linux, CTRL+C permite interrumpir la ejecución del programa (en este caso, interrumpir la depuración con gdb).
  • ENTER: Presionar la tecla ENTER sin ningún comando, ejecutará el comando inmediatamente anterior.
  • CTRL+L: Refresca la terminal y resuelve problemas de visualización.
  • CTRL+P y CTRL+N: Permite navegar entre los comandos escritos previamente.
  • xxxx: Cambio de contextos (pendiente de actualización del manual).

Atajos de teclado para modificar los comandos introducidos

    • CTRL+B y CTRL+F: Permite avanzar o retroceder un caracter a la vez de lo que está siendo escrito.
    • CTRL+B y CTRL+F: Permite avanzar o retroceder un caracter a la vez de lo que está siendo escrito.
    • CTRL+_ o CTRL+X+CTRL+U: Deshacer la última edición realizada en la línea, se puede repetir de forma recurrente hasta llegar a una línea vacía.
  • CTRL+A: Moverse al inicio de la línea.
  • CTRL+E: Moverse al final de la línea.
  • ALT+F: Avanzar por palabras completas.
  • ALT+B: Retroceder por palabras completas.
  • CTRL+K: Corta la línea de texto escrita y lo pone en un buffer temporal.
  • CTRL+Y: Pega el texto (comando) que se encuentre en el buffer, a partir de la posición actual del cursor.
  • Fuente: Documento presente en el manual de GDB.

Comandos (Opciones) Importantes

A continuación listo los “comandos” que más utilizo o que por lo menos me parecen más útiles/importantes (si ya conoces otros que no aparecen en la lista, no dudes en decirlo en los comentarios para agregarlos a esta entrada).

  • start: Inicia la depuración deteniendo la ejecución al inicio de la función main( ), en caso que el programa haya terminado su ejecución, lo reinicia.
  • start arg1 arg2 arg3 ... Permite pasar argumentos al programa analizado.
  • run: Igual que start aunque ejecuta el programa (o lo reinicia) hasta encontrar un breakpoint o hasta alcanzar el final del programa.
  • until NNN: Permite saltar loops, es decir, evita tener que iterar manualmente el ciclo (como ocurriría utilizando next o step). El valor en NNN es un número que corresponde a la línea siguiente una vez se termina el ciclo (si la llave que cierra el bucle está en la línea 17 entonces escriba until 18).
  • watch variable: Vigila la variable indicada y nos avisa cada vez que su valor sea modificado, mostrando además cada vez su valor anterior y el nuevo (todos los watchpoint se eliminan cuando se reinicia el programa).
  • rwatch variable: Vigila la variable indicada, alertando cuando el valor de la variable es leído.
  • continue [c]: Continua la ejecución del programa hasta el siguiente breakpoint (o watchpoint) o hasta la finalización del mismo sino hay más puntos de parada.
  • next  [n]: Avanza instrucción por instrucción en el programa, sin embargo a diferencia de step no entra en detalles de las subrutinas (funciones) cuando se encuentra con una instrucción que hace algún llamado a función.
  • step [s] n_pasos: Recorre el programa instrucción por instrucción y cuando encuentra rutinas (funciones) entra en ellas para depurarlas también, sin embargo en funciones precompiladas como por ejemplo strcpy o printf no entrará en detalles.
  • break [b] opción:
    • número_línea
    • nombre_función
  • info opción: Muestra información referente a la opción que se le indica, algunas de dichas opciones son las siguientes:
    • watch: Lista todos los watchpoints o variables vigiladas.
    • functions: Lista todas las funciones o sub-rutinas presentes en nuestro programa. locals: Entrega información sobre las variables en el contexto en el cual se encuentra la ejecución.
  • delete número_breakpoint: Elimina el breakpoint indicado.
  • quit [q]: Terminamos la sesión de depuración del software que estámos probando.
  • print [p] variable: Permite imprimir el valor contenido en variable.
  • list: Imprime por defecto 10 instrucciones del código fuente que está al rededor de la intrucción actual.

Modificar el Valor de las Variables

Podemos modificar el valor de una variable mediante la orden set var, por ejemplo supongamos que queremos hacer que una variable llamada saldo_ptr (que es un puntero) apunte a la variable saldo.

(gdb) set var saldo_ptr = &saldo

Así, en adelante la variable saldo_ptr tendrá asignada la dirección de la variable saldo. El anterior es solo un ejemplo muy sencillo de como modificar los valores con la orden set var.


Breakpoints (Puntos de Control) Condicionales

La potencia de gdb nos permite asignar breakpoints o puntos de parada solo cuando se cumpla una determinada condición. Supongamos que estamos en medio de una ejecución y queremos poner un break solo si la variable x en nuestro caso tiene el valor 1, entonces en la terminal de gdb la sintaxis es la siguiente:

(gdb) break if x == 1

Tenga en cuenta, que la ejecución puede ser reanudada con el comando run y estos breakpoints no se borrarán.


Tutoriales Recomendados

A continuación dejo algunos tutoriales o recursos recomendados para que inicies con la depuración de software utilizando GDB.



Espero que esta información te haya resultado útil o cuando menos, interesante. Esto es todo por ahora en cuanto a este pequeño manual de trabajo con GDB, recuerda que al igual que otros manuales en este blog, estará en constante actualización con tus comentarios, recursos y nuevas ideas. Nos leemos en los comentarios o en una próxima entrada del blog.

Author: Julio César Echeverri M.

Anuncios