Guía práctica de estudio: Depuración de programas

Anuncio
Guía práctica de estudio:
Depuración de programas
Elaborado por:
M.C. Edgar E. García Cano
Ing. Jorge A. Solano Gálvez
Revisado por:
Ing. Laura Sandoval Montaño
Guía práctica de estudio: Depuración de programas
Objetivo:
Ejecutar un programa bajo el contexto de depuración con la finalidad de encontrar de
forma precisa los errores de ejecución.

Introducción
Cuando un programa falla (no termina su ejecución de manera correcta), la mayoría de las
veces, el compilador envía cierta información que permite determinar dónde se encuentra
el problema. Empero, no siempre es así y es más complicado saber dónde falla el
programa y cómo corregirlo. En esos casos es mejor ejecutar el programa en un contexto
controlado para saber, exactamente, donde está fallando.
La depuración se refiere al hecho de poder ejecutar un programa en un ambiente
controlado de manera que se pueda estudiar el flujo de ejecución, la pila de llamadas, los
valores de las variables, etcétera.
Por ejemplo, el siguiente código genera un error al ejecutarse debido a la falta del carácter
ampersand cuando se lee el valor numérico:
int funcion() {
int num;
printf("Cuántos elementos tiene el arreglo?\n");
scanf("%d",num);
printf("El número de elementos del arreglo es: %d\n", num);
return num;
}
Si se ejecuta el programa anterior, debe enviar una salida de error del siguiente tipo:
$> ./debug
Violación de segmento (core dumped)
1
Debido al mensaje de error generado, la experiencia dice que falló al intentar acceder a una
localidad de memoria no reservada pero, ¿cómo saber en qué parte del programa está el
error?
En este caso es fácil localizar donde está el problema, sin embargo, cuando el código crece
y se tienen cientos de líneas la corrección no es tan directa, es ahí donde los depuradores
adquieren importancia.
La mayoría de los entornos de programación permiten depurar programas realizando una
ejecución paso a paso y consultar los valores que van tomando las variables, de manera
que se puede realizar una traza para detectar dónde y por qué se producen los errores y
corregir los mismos.
gdb (ventana de comandos)
gdb es una aplicación que permite depurar otros programas escritos en cualquier lenguaje
de programación pero compilados con gcc (GNU Compiler Collection, antes GNU C
Compiler).
Ejemplo
int funcion() {
int num;
printf("Cuántos elementos tiene el arreglo?\n");
scanf("%d",num);
printf("El número de elementos del arreglo es: %d\n", num);
return num;
}
Para depurar el programa anterior utilizando gdb se debe compilar el archivo fuente con
gcc y utilizando la bandera -g:
gcc -g archivo.c -o archivo
Cuando se utiliza la bandera -g se crea un archivo un poco más grande, ya que contiene
más información para la depuración.
2
Una vez compilado el archivo se puede ejecutar en un ambiente controlado por gdb de la
siguiente manera:
gdb ./archivo
La línea anterior genera la siguiente salida:
GNU gdb 6.3.50-20050815 (Apple version gdb-1705)
Copyright 2004 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 "x86_64-apple-darwin"...Reading symbols for
shared libraries .. done
(gdb)
Lo que indica que el programa ya se está ejecutando bajo el depurador gdb. El depurador
posee diferentes comandos para ir corrigiendo el programa.
El comando l (list) muestra el código fuente del programa. También se puede indicar la
línea a partir de la cual listar el mismo:
(gdb) l 1
1
#include <stdio.h>
2
#include <stdlib.h>
3
4
int funcion() {
5
int num;
6
7
printf("Cuántos elementos tiene el arreglo?\n");
8
scanf("%d",num);
9
printf("El número de elementos del arreglo es: %d\n",
num);
3
Dentro del entorno de gdb se pueden realizar diversas acciones sobre el código. Si se desea
ejecutar el programa se teclea r (run):
(gdb) r
Starting program: /home/gdb/depurar
Cuántos elementos tiene el arreglo?
5
Program received signal SIGSEGV, Segmentation fault.
0x00390b2f in _IO_vfscanf_internal () from /lib/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.12.90-17.i686
También se pueden crear puntos de ruptura (breakpoint). Los puntos de ruptura o de
interrupción sirven para detener la ejecución de un programa, si un programa falla en
cierto pedazo de código, se recomienda establecer un breakpoint para deterner la
ejecución en ese punto y ejecutar línea a línea las siguientes instrucciones para ver dónde
está el error. Para crear un punto de ruptura se ejecuta el comando b (breakpoint) y el
número de línea donde se quiere establecer el punto:
(gdb) b 7
Breakpoint 1 at 0x804847a: file depurar.c, line 7.
Una vez establecido un punto de ruptura se puede ejecutar el programa (con el comando
r) y la ejecución se detendrá justo en el punto establecido.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/gdb/depurar
Breakpoint 1, funcion () at depurar.c:7
7
printf("Cuántos elementos tiene el arreglo?\n");
(gdb)
Cuando el programa se detiene por un punto de ruptura se tienen tres posibilidades:
continuar la ejecución, saltar al siguiente paso o saltar a la siguiente línea.
4
Si se desea continuar con la ejecución normal del programa se presiona la tecla c
(continue):
(gdb) c
Continuing.
Cuántos elementos tiene el arreglo?
5
Program received signal SIGSEGV, Segmentation fault.
0x00390b2f in _IO_vfscanf_internal () from /lib/libc.so.6
Para depurar el programa se debe ejecutar instrucción a instrucción. Si se desea ejecutar la
siguiente instrucción se debe presionar la tecla s (si la siguiente instrucción es una llamada
a función se ingresará a la misma):
Breakpoint 1, funcion () at depurar.c:7
7
printf("Cuántos elementos tiene el arreglo?\n");
(gdb) s
Cuántos elementos tiene el arreglo?
8
scanf("%d",num);
Si se desea ejecutar la siguiente línea de código se puede presionar la tecla n (si el siguiente
paso es una llamada a función se ejecuta sin entrar al cuerpo de la misma):
Breakpoint 1, funcion () at depurar.c:7
7
printf("Cuántos elementos tiene el arreglo?\n");
(gdb) n
Cuántos elementos tiene el arreglo?
8
scanf("%d",num);
En cualquier momento es posible imprimir el valor de una variable, para ello se utiliza el
comando p (print) seguido del nombre de la variable que se desea mostrar:
Breakpoint 1, funcion () at depurar.c:7
7
printf("Cuántos elementos tiene el arreglo?\n");
(gdb) p num
$1 = 5033972
Para eliminar un punto de ruptura se utiliza el comando delete (d) y el punto a eliminar:
(gdb) delete 7
5
Para mostrar los breakpoints que se han creado en el programa se invoca el comando info
breakpoints:
(gdb) info breakpoints
Num
Type
Disp Enb Address
What
1
breakpoint
keep y
0x0804847a in funcion at depurar.c:7
También se puede ignorar un punto de ruptura, es decir, el depurador no se detendrá en
ese punto de ruptura. Para ignorar un breakpoint se utiliza el comando ignore y se indica
el punto que se desea ignorar:
(gdb) ignore 2
Para salir de gdb se presiona la tecla q o el comando quit:
(gdb) q
Existen varias opciones más de gdb que se pueden ver dentro del manual o en la
información del comando:
$ man gdb
$ info gdb
6
Code Blocks (entorno gráfico)
Code Blocks es un entorno de desarrollo gráfico que permite depurar programas de
manera gráfica utilizando el contexto de debug (depurador) al momento de ejecutar el
programa.
Para depurar un programa es necesario crear un nuevo proyecto de consola (Console
application)
7
Creación de una nueva aplicación de consola
8
Al final se pregunta qué opciones habilitar Debug o Release. La opción Release permite
genera la aplicación ejecutable, la opción debug permite ejecutar el programa en un
entorno controlado por Code Blocks.
9
Cuando se agrega un nuevo archivo al proyecto, se puede activar el modo release o el
modo debug o ambos.
Una vez activado el modo debug se puede abrir el programa y proceder a utilizar el
depurador.
10
Para establecer puntos de ruptura en el programa solo es necesario dar un clic a lado del
número de línea donde se desea agregar. Para retirar los breakpoints es necesario realizar
el mismo proceso (clic) sobre la línea.
11
Para depurar el programa se debe compilar y después en el menú Debug se presiona Start
/ Continue. El programa comenzará su ejecución (aparece la ventana de comandos) y se
detendrá en el punto establecido.
12
Para continuar la ejecución del programa se puede ir al menú Debug y presionar Star /
continue.
13
Así mismo, en el menú Debug existe varias instrucciones para la depuración del código
(Stop debugger, Next line, Next instruction, etc.). Si se selecciona, por ejemplo, Next line,
el programa salta a la siguiente línea.
14
En el menú Debug está la opción para imprimir la pila (Information -> Current stack
frame).
Si el usuario requiere ingresar información al programa se muestra la ventana de
comandos.
15
En cuanto se genera el error, Code Blocks envía una ventana con la traza del mismo
indicando la línea que falló.
16
En cualquier momento se puede ver el valor de una variable, para ello sólo se da clic
derecho sobre la variable y se selecciona "watch 'nombreVariable'".
17
Si el programa se ejecuta en modo release (menú Build, submenú Run), el programa no se
detiene en los puntos de ruptura, esas marcas solo funcionan cuando el programa se
ejecuta en un entorno controlado (en modo Debug).
18
Bibliografía
man gdb
info gdb
http://wiki.codeblocks.org/index.php?title=Debugging_with_Code::Blocks
19
Descargar