Los comandos descritos hasta ahora permiten una ejecución
controlada de un programa, pero cuando el depurador es realmente eficiente
es cuando hay que localizar un error de ejecución. Generalmente, ese error
se manifiesta como una terminación abrupta (por ejemplo segmentation
fault
). Cuando el programa se ejecuta desde el depurador, esa
terminación retorna el control al depurador con lo que es posible utilizar
comandos para inspeccionar el estado en el que ha quedado el
programa.
Uno de los comandos más útiles del depurador es print (o su abreviatura p). Como argumento recibe una expresión, y su efecto es imprimir el valor resultante de evaluar dicha expresión. Este comando puede recibir el nombre de cualquier variable que esté visible en ese instante en la ejecución del programa. El contenido de una de estas variables se muestra por pantalla simplemente escribiendo el comando seguido del nombre.
Breakpoint 2, main (argc=1, argv=0xfefff604) at gdb_use.c:42 42 function(buf); (gdb) s function (table=0x804a008) at gdb_use.c:16 16 for (y = 0; y < SIZE - 1; y++) (gdb) n 18 table[y].data = y; (gdb) n 19 table[y].next = &table[y + 1]; (gdb) n 16 for (y = 0; y < SIZE - 1; y++) (gdb) p table[0].data $1 = 0 (gdb) p table[0].next $2 = (struct data_unit *) 0x804a010 (gdb)
Aparte de nombres de variables, print acepta expresiones aritméticas en las que pueden aparecer nombres de variables (por ejemplo: print x + 2) o direcciones de memoria.
(gdb) p *table[0].next $3 = {data = 0, next = 0x0} (gdb) p table[0].next->data $4 = 0 (gdb)
Nótese que el último comando print tiene como parámetro la expresión table[0].next->data. El depurador evalua esta expresión de forma idéntica a como lo hace el compilador, con los valores existentes en ese instante e imprime el resultado.
Algunas expresiones pueden ser útiles para conocer en detalle qué está sucediendo en un programa. Por ejemplo, si en un programa en C se reserva espacio para una tabla de 100 enteros, la línea correcta a escribir es:
tabla = (int *)malloc(100 * sizeof(int));
El depurador puede evaluar la expresión sizeof(int) y mostrar su resultado. Esta es una forma de saber el tamaño con el que trabaja el compilador en la plataforma que se está utilizando. En el programa de ejemplo se puede ver el tamaño que ocupa la estructura de datos data_unit mediante el comando:
(gdb) p sizeof(struct data_unit)
$5 = 8
(gdb)