Depuración con GDB y Electric-Fence para las masas

Curso acelerado de Electric-Fence y Gdb

Electric-Fence o como cazar a esos punteros tan maleducados

El electric fence no es más que una librería que sustituye a malloc, free y compañía, por otras funciones que marcan las zonas de memoria por encima (y por debajo, si así lo hemos configurado), como no accesibles, de modo que si por ejemplo al leer de una cadena (o peor, al escribir), o un array nos pasamos, por poquito que sea, el programa dará un Segmentation Fault. Pues vaya m.... pensará alguno.

Pues no señor. Cuando enlazamos con el electric-fence el fallo nos lo dará justo donde nos hayamos ido, no 500 instrucciones más tarde (por algo lo usan en Pixar).

De este modo, sólo tenemos que lanzar el gdb, ir ejecutando, y cuando nos de el segmentation fault, ya sabemos que ahí esta el fallo.

Como utilizarlo: Más fácil imposible, simplemente enlazar con la librería estática con -lefence en los parámetros del gcc. Esto hará que el programa sea muuuuuuuuuuuuuuucho más lento y ocupe muuuuuuuuuuuuuuuuuucha más memoria, pero para depurar eso no importa. Esto nos da una configuración por defecto de que detecte los accesos más allá del límite, pero no antes.

Todo lo demás se configura con variables de entorno, la más util es la opción EF_PROTECT_BELOW que nos detectará también los accesos por debajo de la memoria asignada. En realidad no tiene muchas más opciones, pero la página man no tiene desperdicio: Hay que leerla (no es muy larga).

Gdb básico para las masas

Gdb es un gran depurador con multitud de opciones interesantes, pero la mayor parte del tiempo vamos a usar muy pocas de ellas.

Para poder depurar un programa es necesario haberlo compilado con la opción -g del gcc y por supuesto no stripearlo. Después simplemente:

gdb programa

Nos saldrá un fea pantalla como:

GNU gdb 19990928
Copyright 1998 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"...
(gdb)

El (gdb) es el prompt. Podemos obtener ayuda con help y help sección (las secciones posibles salen poniendo help sin nada).

Dejémonos de rollos.

Para establecer los argumentos que le pasaríamos al programa:
set args argumento1 argumento2 etc

Para establecer breakpoints:
break funcion

Para eliminar breakpoints:
clear funcion

Por ejemplo, la primera vez haríamos:
break main

Para depurar el programa desde el principio. Una vez hemos puesto los breakpoints y los argumentos empezamos a ejecutar con:
run

Esto nos sacará la primera línea de nuestro programa a partir del primer breakpoint establecido (en este caso la función main). Para obtener un listado de las líneas cercanas:
list

que puede abreviarse como 'l'. En general casi todos los comandos tienen una abreviatura como primera letra salvo cuando puede producirse ambiguedad.

Para pasar a la siguiente línea:
next (abreviado como n)

El next puede aceptar un argumento que es el número de líneas que queremos ejecutar. Si pulsamos intro se repite el último comando introducido (útil para ejecutar rápidamente varios next).

next si encuentra una llamada a función no se introduce en ella. Esto es útil para detectar rápidamente donde nos falla el programa recorriendo las llamadas a función del programa y ver en cual de ellas falla. Después podemos volver a ejecutar pero al llegar a la función que falla (si no nos hemos dado cuenta ya de cual es el fallo) con:
step (abreviado como s)

exactamente igual que next, pero introduciéndose en las funciones. Si está función llama a su vez a varias otras funciones es recomendable repetir el proceso anterior (next, localizar la función en la que falla, meternos con step, next, localizar...) hasta que demos con la línea de código exacta que falla sin llamar a otra de nuestras funciones.

Por supuesto también podemos (y debemos) imprimir los valores de las variables y estructuras que consideremos 'sospechosos'. Esto se hace con:
print variable (abreviado como p).

En el caso de cadenas tenemos printf:
printf "cadena con un formato %d muy bonito:%s",entero, cadena

que admite los mismos especificadores de formato que el printf de C (sin los paréntesis). Si estamos utilizando el DDD (gráfico) podemos poner una ventanita donde nos sale continuamente el valor que tienen ciertos datos. Además con print también podemos cambiar el valor de los datos:
print dato=loquequeramos (comillas si es una cadena).

Con esto ya hay para ir tirando (para más ayuda, el info gdb).

Ahora vamos a hablar de los archivos core, esos molestos archivos de 6 megas que nos deja siempre el netscape como recuerdo de su inoperancia. Pues son extremadamente útiles para depurar los programas. Podemos pensar en el core como en el cadaver del programa que podemos examinar, si el programa fue compilado con -g y no stripeado. Para utilizarlos se hace con:
gdb programa -c core

(importante que 'programa' y el proceso que generó el core sean la misma versión). Esto (con suerte) nos dirá en que línea fallo el programa (si las fuentes están en el mismo directorio), y con más suerte aún nos permitirá ver los valores de variables y demás.

Que el core sea realmente informativo depende de muchos factores como la fase lunar, si nos hemos afeitado (tiendo a pensar que cuando estoy recién afeitado y limpio los cores son más amigables) y demás.

Un último consejo. El gcc es un compilador algo peculiar porque nos deja compilar con símbolos de depuración y optimizar. Mi consejo es que para depurar paseis de las optimizaciones sino quereis ver cosas raras cuando estemos ejecutando paso a paso (líneas que se saltan, while que empiezan a ejecutarse por debajo, etc.)

Y se acabó: man efence, info gdb son vuestros amigos.

El próximo documento: DDD y como evitar perder la cordura ante los Heisenbugs (1).

(1): Dícese del bug que provoca un fallo en nuestro programa en cualquier circunstancia menos cuando lo ejecutamos con el depurador, en cuyo caso el programa funciona a la perfección. Puedo asegurar que no son una historia de miedo que corra de maestros a alumnos, como el coco y demás: Existen. Rezo por vosotros por que no encontreis ninguno.


(C) 2000-2001 Juan José �lvarez Martínez.
Puede distribuir este documento libremente bajo los términos de la licencia Document GPL.
comments powered by Disqus