PRÁCTICAS DE SISTEMAS OPERATIVOS
MANEJO DEL DEPURADOR
Cuando se producen errores en tiempo de ejecución, hay que depurar
el programa. El error en tiempo de ejecución se debe habitualmente a un
mal diseño de nuestro programa. Para corregir errores en tiempo de
ejecución, hay que proceder en dos pasos:
- Acotar al máximo la parte del código fuente que está fallando.
- Una vez se sabe en qué zona del programa se está produciendo
el error, hay que proceder a solucionarlo. Para ello, hay
que enfrentar el comportamiento esperado con el comportamiento
que en realidad sucede. Hay que plantear una hipótesis de lo
que está fallando, y con esta hipótesis, modificar el programa
de modo que la próxima ejecución sea diferente en el caso de
que la hipótesis sea verdadera o no.
A veces, al no disponer de otras herramientas o debido a la simplicidad
de la prueba, se puede simplemente modificar el código fuente incluyendo
alguna orden que imprima el valor de alguna variable, un mensaje, etc.
Sin embargo, es preferible usar un programa que se denomina depurador
(debugger). En el servidor, podéis usar el depurador de GNU, el gdb
.
Veamos un ejemplo: queremos usar el depurador con un programa que se
llama limpiador.c
.
- Primero, hay que añadir la opción
-g
cuando se compile
el programa:
<T>/usuarios/gyermo/PRIVADO/SO/PRACTS/LIMPIADOR$ gcc -g limpiador.c -o limpiador
Esta opción del compilador hacer que se incluya en el ejecutable
información acerca del fichero fuente. Esto trae como consecuencia
adicional que si se produce un error en la etapa de enlazado, el
enlazador podrá decirnos en qué línea se produce el error. Esta
opción no se debe dejar cuando el programa esté depurado, pues
hace que su tamaño sea mayor.
- Ahora ejecutamos el programa depurador especificando como primer
argumento el nombre del programa ejecutable que queremos depurar:
<T>/usuarios/gyermo/PRIVADO/SO/PRACTS/LIMPIADOR$ gdb limpiador
Wildebeest is free software and you are welcome to distribute copies of
it under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for Wildebeest; type "show warranty"
for details.
Hewlett-Packard Wildebeest 1.0 (based on GDB 4.16)
(built for PA-RISC 1.1 or 2.0 (narrow), HP-UX 11.00)
Copyright 1996, 1997 Free Software Foundation, Inc...
(gdb)
- Dentro del depurador, podemos usar muchas órdenes diferentes. Veamos
alguna. De todos modos, se puede obtener ayuda con la orden
help
. Lo primero es poder listar el código fuente.
Se hace con la orden l
:
(gdb) l
9
10 #define CTRL_H 8
11
12 int main(int argc, char *argv[])
13 {int fd; off_t tamaNo;
14 long i;
15 char *cp;
16 char *leerp, *escribirp;
17
18 if (argc!=2)
- Podemos poner un punto de ruptura (breakpoint) con la orden
b
. Un punto de ruptura en un lugar del código fuente
donde queremos parar la ejecución del programa para poder
examinar el valor de las variables, por ejemplo:
(gdb) b 18
Breakpoint 1 at 0xc0e8: file limpiador.c, line 18.
- Ahora ya podemos ejecutar el programa. Para ello, damos la orden
run
seguida de los argumentos del programa:
(gdb) run pepe.txt
Starting program: /usuarios/gyermo/PRIVADO/SO/PRACTS/LIMPIADOR/limpiador pepe.txt
Breakpoint 1, main (argc=2, argv=0x7f7e057c) at limpiador.c:18
18 if (argc!=2)
- Como vemos, la ejecución se ha parado justo en el punto de ruptura.
Podemos examinar en este momento el contenido de alguna variable
con la orden
p
.
(gdb) p argc
$1 = 2
(gdb) p argv[0]
$2 = 0x7f7e0000 "/usuarios/gyermo/PRIVADO/SO/PRACTS/LIMPIADOR/limpiador"
(gdb) p argv[1]
$3 = 0x7f7e0037 "pepe.txt"
(gdb) p argv[2]
$4 = 0x0
- Para ejecutar sólo una instrucción, hay que dar la orden
s
.
(gdb) s
24 fd=open(argv[1], O_RDWR);
(gdb) s
25 if (fd==-1)
(gdb) p fd
$5 = -1
- Se puede continuar la ejecución del programa hasta el siguiente
punto de ruptura mediante la orden
cont
.
(gdb) cont
Continuing.
limpiador:open: No such file or directory
Program exited with code 01.
El depurador nos muestra el mensaje que producía el programa original
y nos dice el código de retorno que devolvía al Sistema Operativo.
- Para acabar, hay que dar la orden
quit
.
Análisis de un fichero core
El depurador sirve también para analizar la causa de la producción de un
fichero core
. Por ejemplo, si introducimos el siguiente código:
void main(void)
{char array[13];
array[10000000]='J';}
Lo compilamos y lo ejecutamos, se produce un acceso ilegal a memoria que
se ve reflejado en la interrupción del programa y la generación de un
fichero core
. Este fichero contiene la información acerca
del punto en que se interrumpió y la causa por la que se interrumpió el
programa1:
<T>/usuarios/gyermo/PRIVADO/SO/PRACTS/CORE$ gcc -g prueba.c -o prueba
<T>/usuarios/gyermo/PRIVADO/SO/PRACTS/CORE$ prueba
Memory fault(coredump)
<T>/usuarios/gyermo/PRIVADO/SO/PRACTS/CORE$ ls -l
total 522
-rw------- 1 gyermo profes 185820 Feb 29 00:55 core
-rwxr-xr-x 1 gyermo profes 68896 Feb 29 00:55 prueba
-rw-r--r-- 1 gyermo profes 64 Feb 29 00:55 prueba.c
Para analizar la causa de la detención del programa sólo hay que ejecutar
el depurador especificando el fichero core
como segundo
argumento:
<T>/usuarios/gyermo/PRIVADO/SO/PRACTS/CORE$ gdb prueba core
Wildebeest is free software and you are welcome to distribute copies of
[...]
Copyright 1996, 1997 Free Software Foundation, Inc...
Core was generated by `prueba'.
Program terminated with signal 11, Segmentation fault.
warning: The shared libraries were not privately mapped; setting a
breakpoint in a shared library will not work until you rerun the program.
#0 0xbf54 in main () at prueba.c:4
4 array[10000000]='J';}
#0 0xbf54 in main () at prueba.c:4
4 array[10000000]='J';}
A partir de ahí, se puede usar otras órdenes del depurador, lo que es muy
interesante, pues se puede inspeccionar variables, mirar el estado de la pila de llamadas
a funciones (back
)...
1 En algunos sistemas, en particular en muchos Linuxes,
la generación de ficheros core
está desactivada
por defecto para no desperdiciar espacio del disco duro, pues un usuario
normal no se dedica a depurar los programas que fallan. Para activar la
generación de ficheros core
, hay que escribir:
ulimit -c unlimited
© 2020 Guillermo González Talaván.