Anuncios

Bienvenidos sean a este post, hoy veremos como establecer breakpoints.

Anuncios

En el post anterior vimos algunos comandos que podemos usar en nuestra depuracion de un programa. Uno que mencionamos muy superficialmente fue el breakpoint o punto de interrupcion. Este nos permite asignar una ubicacion donde se interrumpira la ejecucion, sin terminar el codigo, para poder examinar al codigo como esta trabajando hasta ese momento. Pero los breakpoints tienen algunas variedades y pueden hacer otras tareas mas. Para poder verlo de mejor forma vamos a trabajar con el siguiente codigo:

#include <iostream>

float sumar(const float*, int);

int main()
{
        float total;
        float x[] = {1,2,3,4,5};
        float y[] = {6,7,8,9,10};
        total = sumar(x, 5);
        printf("sum(x)=%f\n", total);
        total = sumar(y, 5);
        printf("sum(y)=%f\n", total);

        return 0;
}

float sumar(const float* a, int n)
{
        float ret = 0;
        const float* s = a;
        for(int i=0; i < n; i++, s++)
        {
                ret += *s;
        }
        return ret;
}
Anuncios

Este codigo toma los valores en un array, los suma y devuelve el resultado final. Para usarlo, creamos dos arrays, los pasamos a la funcion y mostramos el resultado en pantalla. Recuerden que para poder usar nuestro depurador al momento de compilarlo deben agregar la opcion -g, de esto hablamos en el post anterior, para que agregue todos los elementos necesarios para trabajar en el ejecutable. Pasemos a ver al primer breakpoint.

Anuncios

breakpoint de funciones

Este es el breakpoint mas basico, lo vimos en el post anterior, y se especifica el nombre de la funcion donde estara este y cuando lo ejecutemos se detendra en ese punto especifico para que podamos ver como trabaja hasta ese momento. Tomemos a nuestro ejemplo, en el depurador escriban sum y presionen el tabulador (tab) para que lo autocomplete de la siguiente manera:

(gdb) break sumar(float const*, int)
Anuncios

Esto agregara el punto de interrupcion al prototipo de la funcion y cuando lo ejecutamos se detendra en este. Tal como vimos en el post anterior.

Anuncios

breakpoint por posicion

Otra opcion que podemos utilizar es especificar una posicion en nuestro codigo. Para ello debemos pasar primero el nombre del archivo de codigo fuente, seguido de dos puntos y el numero de linea donde asignarlo. Veamos el siguiente ejemplo:

(gdb) break depurar.cpp:10
Anuncios

Como pueden ver es muy simple, y esto hara lo mismo que antes pero en otra parte especifica. Esto puede ser especialmente util si tenemos cierta desconfianza de una seccion del codigo o simplemente queremos ver si en ese punto no ocurre nada raro. Sigamos con el siguiente breakpoint.

Anuncios

breakpoint condicional

Este tipo de breakpoint se aplicara solamente si se cumple la condicion. Vayamos al depurador y ejecutemos el siguiente comando:

(gdb) break depurar.cpp:22 if ret==0
Anuncios

Es muy similar al breakpoint anterior pero se agrega un condicional. Esto hace que el breakpoint se active solamente si se cumple esa condicion, en caso contrario lo omite y hace como si no existiese.

Anuncios

Listar breakpoints

El depurador nos brinda la posibilidad de poder listar todos los breakpoints que hayamos creado.. Para ello, debemos usar el siguiente comando:

(gdb) info breakpoints
Anuncios

Luego de ejecutarlo nos mostrara un listado de la siguiente manera:

(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000001273 in sumar(float const*, int)
                                                   at depurar.cpp:20
2       breakpoint     keep y   0x00000000000011e3 in main() at depurar.cpp:10
3       breakpoint     keep y   0x000000000000128d in sumar(float const*, int)
                                                   at depurar.cpp:24
        stop only if ret==0
(gdb)
Anuncios

Recuerden que esto va a variar en base a la cantidad de los breakpoints existentes pero su estructtura es la misma. Tendra un numero de identificacion, el tipo, si esta activo, la direccion de memoria, donde se encuentra y si tiene una condicion, vean el numero 3.

Anuncios

Eliminar breakpoints

Para eliminar un breakpoint se necesita el numero de identificacion, este dato lo podemos obtener con el comando anterior. Siendo el valor la primera columna, veamos como se realiza esto:

(gdb) delete breakpoints 2
Anuncios

En este caso le pase para que elimine al segundo breakpoint. Si volvemos a pedir un listado de los breakpoints nos devolvera lo siguiente:

(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000001273 in sumar(float const*, int)
                                                   at depurar.cpp:20
3       breakpoint     keep y   0x000000000000128d in sumar(float const*, int)
                                                   at depurar.cpp:24
        stop only if ret==0
(gdb)
Anuncios

Observen como mantuvo los identificadores pero ya no existe mas el segundo breakpoint. Tambien use una abreviatura para el comando de listado de breakpoints.

Anuncios

Como remover una condicion de un breakpoint

Una modificacion que podemos hacer es eliminar la condicion de un breakpoint. Esto gracias al identificador, tal como antes pero con el siguiente comando:

(gdb) cond 3
Breakpoint 3 now unconditional.
(gdb)
Anuncios

Usamos a cond y le pasamos el identificador, este elimina la condicion y nos lo informa en la consola. Ahora si mostramos nuevamente los breakpoints, veremos lo siguiente:

(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000001273 in sumar(float const*, int)
                                                   at depurar.cpp:20
3       breakpoint     keep y   0x000000000000128d in sumar(float const*, int)
                                                   at depurar.cpp:24
(gdb)
Anuncios

Observen que siguen los dos breakpoints pero ahora el numero 3 se ejecutara porque al eliminar el condicional nada impide que se ejecute.

Anuncios

Watchpoint

Este puede detener la ejecucion cuando el valor de una variable cambia sin necesidad de predecir en que linea puede ocurrir. Tenemos tres tipos para este comando:

  • watch: se deterndra cuando una escritura ocurra
  • rwatch: esto lo detendra cuando ocurra una lectura
  • awatch: y este lo detendra cuando ocurra una lectura y/o escritura
Anuncios

Para activarlo deben estar en plena ejecucion del depurador. Una vez dentro, si tomamos nuestro codigo pueden ejecutar el siguiente comando cuando se detenga:

(gdb) watch total
Hardware watchpoint 2: total
(gdb)
Anuncios

Aqui le pedimos que observe a total, si pasan next, o step pasara al siguiente comando pero ahora si usamos continue continuara pero cuando se modifique la variable se detendra y ahora nos mostrara lo siguiente:

(gdb) watch total
Hardware watchpoint 2: total
(gdb) c
Continuing.

Hardware watchpoint 2: total

Old value = 0
New value = 15
main () at depurar.cpp:11
11              printf("sum(x)=%f\n", total);
(gdb) c
Continuing.
sum(x)=15.000000

Hardware watchpoint 2: total

Old value = 15
New value = 40
main () at depurar.cpp:13
13              printf("sum(y)=%f\n", total);
(gdb) c
Continuing.
sum(y)=40.000000

Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
__libc_start_call_main (main=main@entry=0x555555555159 <main()>,
    argc=argc@entry=1, argv=argv@entry=0x7fffffffe318)
    at ../sysdeps/nptl/libc_start_call_main.h:74
74      ../sysdeps/nptl/libc_start_call_main.h: No existe el fichero o el directorio.
(gdb)
Anuncios

Observen como ahora por cada vez que pasamos con continue, sigue hasta que se detiene tal como comentamos anteriormente.

Anuncios

continue

Es otra opcion para continuar con la ejecucion de la depuracion pero a diferencia de next y step, este continuara hasta el proximo breakpoint, watchpoint o error, asi como vimos anteriormente. En caso de no existir alguno mas procede hasta el final del codigo como se vio en el ejemplo anterior.

Anuncios

finish

Este es para cuando estamos dentro de una funcion y queremos avanzar hasta el final de la misma. Para inmediatamente enviarnos a la siguiente linea desde donde se llamo a la funcion en el codigo.

Anuncios

En resumen, hoy hemos visto las distintas formas de establecer un breakpoint, asi como tambien obtener informacion de ellos, eliminarlos, transformarlos para que no tengan una condicion, asi como tambien eliminarlos para cuando no sean necesarios, otro tipo de breakpoint como es un watchpoint y un par de comandos mas. Espero les haya resultado de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios

Donación

Es para mantenimento del sitio, gracias!

$1.50