GDB para depurar programas en C/C++ en GNU/Linux
December 14, 2007 GNU/Linux, Programación 5 CommentsMiremos la descripción de gdb sacada del mismo man:
El proposito de un depurador como GDB es permitir al usuario ver lo que
esta ocurriendo “dentro” de otro programa mientras que se esta ejecu-
tando — o lo que estaba haciendo en el momento que fallo.GDB puede hacer cuatro tipo de cosas (mas otras cosas para dar soporte
a estas) para ayudarte a capturar errores en el acto:o Comenzar tu programa, especificando cualquier cosa que pueda
afectar a su comportamiento.o Hacer que tu programa se pare al cumplirse las condiciones
especificadas.o Examinar que ha pasado, cuando tu programa se ha parado.
o Cambiar cosas de tu programa, de tal manera que puedas experi-
mentar corrigiendo los efectos de un fallo y continuar para des-
cubrir otros.
Generalmente todas las distribuciones GNU/Linux ya tendrán este depurador instalado o en su defecto, lo encontraran en su administrador de paquetes preferido/formato de paquetes preferido (deb,rpm, etc..).
Me entere del programa entrado al canal de IRC de gentoo en freenode.org, la cuestión es que probaba el proyecto de fin de semestre para “Programación de Sistemas” en Gentoo, como la interfaz gráfica es usando Ncurses no creí que hubiera error alguno y bueno, paso lo que menos me imagine el programa brinco y aborto la ejecución al iniciar la compilación (el proyecto es un “Editor de Textos” para implementar el manejo de un compilador
). Entre mi dije, demonios!! yo que creía que todo iba ser miel sobre hojuelas
, en fin, después de probarlo hace unos minutos me encontré con el error y supe solucionar
.
Ahora empecemos con la parte práctica que es la más me gusta, para compilar un código con información útil para gdb hay que hacerlo de la siguiente manera (opción: –ggdb):
g++ [nombre].cpp -lncurses -ggdb -o [nombre_binario]
Para iniciar gdb con el binario es tan simple como poner el comando con el mismo nombre y el ejecutable a depurar:
Se puede ejecutar gdb sin argumentos ni opciones; pero la manera mas
comun de comenzar GDB es con uno o dos argumentos, especificando un
programa ejecutable con el argumento:gdb programa
soullost@UnderHouse ~/c++/curses/editor $ gdb [nombre_binario]
GNU gdb 6.6 Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i686-pc-linux-gnu"... Using host libthread_db library "/lib/libthread_db.so.1". (gdb)
Aquí empieza lo interesante.
Poner un breakpoint (lugar donde se detendrá el programa en ejecución para hacer acciones de depuración):
break [fichero:]funcion
Pone un punto de ruptura en funcion (en fichero).
(gdb) break separar Breakpoint 1 at 0x804ad44
Para iniciar la ejecución de programa:
run [arglist]
Comienza tu programa (con arglist, si se especifica).
(gdb) run
Si establecimos un breakpoint, se detiene el programa y posteriormente después de realizar algunas acciones (como mirar valor de variables, adelantar unas líneas, etc..) queremos que el programa se siga ejecutando normalmente hacemos:
c Continua ejecutando tu programa (despues de parar, p.e. en un
punto de ruptura).
(gdb) c
Para mirar la pila de los eventos guardados por gdb:
bt Backtrace: muestra la pila del programa.
(gdb) bt #0 0xffffe410 in __kernel_vsyscall () #1 0xb7cb7101 in raise () from /lib/libc.so.6 #2 0xb7cb88e8 in abort () from /lib/libc.so.6 #3 0xb7cedcbb in __libc_message () from /lib/libc.so.6 #4 0xb7cf3a00 in malloc_printerr () from /lib/libc.so.6 #5 0xb7cf56f9 in free () from /lib/libc.so.6 #6 0x08049bd8 in analizadorLexico () #7 0x0804ae76 in separar () #8 0x0804c727 in main ()
En este caso nos menciona más o menos lo siguiente:
#2 Abortado
#3 Aviso Error
#4 Aviso Error
#5 Ejecución de la función free()
#6 Entra a analizadorLexico()
#7 Entra a separar()
#8 Entra a main
Ya nos dijo que el error existe después de llamar a free(), para asegurarnos ejecutamos nuevamente el programa con las opciones next y step:
next. Nos dice en que línea va ejecutando el programa pero con un peculiaridad, si existe la llamada a una función simplemente la ejecuta y continua con la línea posterior después de la llamada a la función.
step. Lo mismo que lo anterior pero este si entra a la función y no simplemente la ejecuta, por lo que si se topa con alguna, entrará a la función y se ejecutará paso a paso desde la primera línea y al terminar regresará al punto donde fue llamada la función para continuar.
Ejemplo, continuando con la depuración del editor que nos causaba problemas:
(gdb) next
660 while(ptrToken){
(gdb) next
661 strcpy(tokens[z].nombre,ptrToken);
(gdb) next
662 tokens[z].linea=i;
(gdb) next
663 z++;
(gdb) next
664 ptrToken = strtok(NULL," ");
(gdb) next
660 while(ptrToken){
Cuando se usa step y pasa a ejecutar una función paso a paso.
(gdb) step analizadorLexico (token=0x804f7a0 "inicio", linea=0) at main.cpp:702 702 int w=0;
Si en algunas casos queremos mirar el valor de alguna variable podemos usar print:
print expr
Muestra el valor de una expresion.
(gdb) print tokens[i]
$1 = {nombre = "inicio\000\000\000", linea = 0}
Y bueno, es algo básico que me ayudó a mirar el error que provocaba que el programa abortara la ejecución, el error tuvo que ver con la llamada a free() y que con comentarlo bastó para solucionarse
y fue bastante raro porque en Dev C++ no provoco error alguno y el programa en windows corre bien.
Corriendo el programa en gnome-terminal
Si están interesados en más información sobre gdb pueden mirar:
man gdb (consola)
info gdb (consola)
http://www.ldc.usb.ve/~figueira/Cursos/ci3825/taller/material/gdb.html
http://www.ac.uma.es/educacion/cursos/informatica/FundSistOp/gdb.pdf
Hay bastante más información en google
, nos vemos
.



