Anuncios

Bienvenidos sean a este post, hoy hablaremos sobre una tecnica para analizar nuestros codigos.

Anuncios

Pero que es debug o tambien conocido como depuracion? Es la accion de visualizar los recursos utilizados por nuestro codigo fuente al momento de ejecutarlo. Esto es especialmente util para ver y analizar sus comportamientos.

Anuncios

Los compiladores pueden trabajar o no con simbolos. Si lo hacemos con simbolos se creara un mapeo necesario entre el codigo fuente y el programa generado. Esto es asi para poder apuntar la linea del codigo fuente correspondiente a la siguiente accion del programa. El debugger o depurador permite las siguientes acciones en el codigo fuente:

  • Ver los resultados de cada instruccion ejecutada
  • Ver el estado actual de cada variable
  • Examinar estructuras de datos complejos
  • Visualizar el valor de los datos miembros en las clases
  • Ver los valores actuales en memoria de varios apuntadores y otras ubicaciones en memoria
Anuncios

De manera predeterminada, al momento de compilarlo lo hacemos sin simbolos. Por lo tanto, no se genera este mapeo para poder vincular al programa con el codigo fuente para que el depurador pueda manipularlo. Esto es la conducta predeterminada porque realiza una compilacion mas rapida. Pero podemos modificar esa conducta, para ello debemos ejecutar la compilacion de la siguiente manera:

$ g++ -g codigo_fuente -o programa
Anuncios

Simplemente agregando esa opcion nos permite establecer todo el codigo para la depuracion. Veamos un ejemplo, para ello generen un archivo con el siguiente codigo:

#include <fstream>
#include <iostream>

int main()
{
        char archivo[80];
        char texto[255];
        std::cout << "Nombre del archivo: ";
        std::cin >> archivo;
        std::ofstream abrir(archivo);
        std::cout << "Ingresa un texto: ";
        std::cin.ignore(1, '\n');
        std::cin.getline(texto,255);
        abrir << texto << std::endl;
        abrir.close();
        std::ifstream leer(archivo);
        char ch;
        while(leer.get(ch))
                std::cout << ch;
        leer.close();
        return 0;
}
Anuncios
Anuncios

Este codigo esta explicado en este post. De manera muy superficial este nos perrmite crear un nuevo archivo, agregarle un texto y mostrar lo ingresado. Pero aqui lo usaremos para ver las distintas posibilidades que nos brinda el depurador. Para crear nuestro enlace entre el codigo y el programa para la depuracion, debemos compilarlo como indicamos anteriormente. Este se generara internamente y no veremos nada mas en el directorio.

Anuncios

Nuestro siguiente paso sera agregar la herramienta para la depuracion. Para ello usaremos al depurador GNU propio de G++. Por lo general, se encuentran en repositorios de cualquier distro de Linux. Para instalarlo en debian deben usar el siguiente comando:

$ sudo apt-get install gdb
Anuncios

Este agregara una serie de componentes extras y una vez finalizado podemos comenzar a usarlo. Si ya compilaron el ejemplo con la opcion -g podemos usarlo al depurador de la siguiente manera:

$ gdb depurar
Anuncios

Simplemente le pasamos el nombre del programa, no del codigo fuente, para ingresar al depurador. Esto hara que nos quedemos con el siguiente prompt:

$ gdb depurar
GNU gdb (Debian 13.1-3) 13.1
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from depurar...
(gdb)
Anuncios

A partir de ahora podemos usar los comandos antes comentados. Probemos de ejecutar el siguiente:

(gdb) b 11
Anuncios

Este establecera un breakpoint en la linea 11. Para esto tambien podiamos haber usado a break 11 pero en un momento hablaremos sobre esto. Esto significa que el programa se ejecutara hasta ese breakpoint. Para correrlo debemos ejecutar lo siguiente:

(gdb) r
Anuncios

Pueden correrlo con esto o con la palabra run. Si lo ejecutan, tendremos una salida como la siguiente:

(gdb) r
Starting program: /home/tinchicus/lenguajes/cpp/04/depurar
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Nombre del archivo: p.txt

Breakpoint 1, main () at depurar.cpp:11
11              std::cout << "Ingresa un texto: ";
(gdb)
Anuncios
Anuncios

Nos pide que ingresemos un nombre de archivo y luego se interrumpe, informando que el codigo tiene un breakpoint en la linea que establecimos. Esto es ideal para cuando necesitamos analizar una parte de nuestro codigo. Por ejemplo, vamos a suponer que tenemos un error en esa parte y necesitamos analizar esa seccion. Con el breakpoint ejecutara hasta donde le indiquemos y podremos centrarnos en ello. Esto es principalmente para descartar si es esta seccion u otra la del codigo que falla. Para continuar debemos usar el siguiente comando:

(gdb) c
Anuncios

Esto hara que retomemos desde el ultimo breakpoint y continuar con la ejecucion del programa. Veamos para el caso de nuestro ejemplo:

(gdb) c
Continuing.
Ingresa un texto: Esto es de prueba.
Esto es de prueba.
[Inferior 1 (process 9221) exited normally]
(gdb)
Anuncios

Como pueden ver continua perfectamente nuestro codigo, tambien porque el mismo funciona perfectamente y no posee ningun error. Vamos a hablar un poco sobre algunos comandos que podemos usar con los breakpoints. Veamos como es el primero:

(gdb) info b
Anuncios

Si pasamos al comando info seguido de la letra b nos devolvera todos los breakpoints asignados. Veamos como es la salida:

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000000128f in main() at depurar.cpp:11
2       breakpoint     keep y   0x00000000000012df in main() at depurar.cpp:14
3       breakpoint     keep y   0x0000000000001319 in main() at depurar.cpp:16
(gdb)
Anuncios
Nota:
Para ver mejor al ejemplo le agregue unos breakpoint mas.
Anuncios

Si observan tenemos varias opciones que nos sirven para poder manejarlas que van desde el identificador, el tipo, disponibilidad, si esta activado, la direccion y en que linea de que archivo y la funcion. Despues tenemos un comando para desactivarlos:

(gdb) disable b
Anuncios

Este desactiva todos los breakpoints que tengamos creados. Para desactivar un breakpoint especifico debemos pasarle el identificador:

(gdb) disable b 2
Anuncios

En este caso, desactiva al segundo breakpoint unicamente. Si lo comprobamos, lo veremos de la siguiente manera:

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000000128f in main() at depurar.cpp:11
2       breakpoint     keep n   0x00000000000012df in main() at depurar.cpp:14
3       breakpoint     keep y   0x0000000000001319 in main() at depurar.cpp:16
(gdb)
Anuncios

Observen que unicamente el breakpoint 2 esta con un estado de desactivado, el resto se seguiran usando cada vez que lo corramos. Asi como los podemos desactivar, tambien los podemos activar. Siendo muy similar al anterior:

(gdb) enable b
Anuncios

Este activara todos los breakpoints que se encuentren asignados. Al igual que en disable, podemos especificar uno mediante el identificador y su sintaxis es la misma:

(gdb) enable b 2
Anuncios

Por ultimo, podemos eliminar acciones en nuestro depurador. Para ello usamos a delete, tomemos como ejemplo un breakpoint. Para eliminar uno debemos usar el siguiente comando:

(gdb) delete breakpoint 2
Anuncios

Esto elimina el segundo breakpoint, si usamos a info nos devuelve lo siguiente:

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000000128f in main() at depurar.cpp:11
3       breakpoint     keep y   0x0000000000001319 in main() at depurar.cpp:16
(gdb)
Anuncios

A continuacion, les dejo una tabla con los comando vistos anteriormente, asi como tambien otros que disponemos:

 DescripcionValor
break [archivo:]funcionEstablece un punto de interrupcion al entrar a funcion en archivo, archivo es opcional
btForma abreviada de backtrace: muestra la pila del programa
cContinua la ejecucion del programa despues del punto de interrupcion
disassemble frameMuestra el codigo binario como codigo en lenguaje ensamblador en vez de lenguaje fuente para un frame
whereNos devuelve el frame actual en uso
display expMuestra el valor de la variable exp cada vez que el programa se detenga
helpMuestra la ayuda en general, acompañado con el comando muestra las opciones de ese comando
list [[archivo:]linea]Muestra ±5 lineas del codigo fuente. archivo y linea especifican el codigo fuente a mostrar y son opcionales
nextEjecuta el siguiente paso del programa sin entrar en las funciones llamadas
print expImprime exp, donde exp puede ser una variable, nombre de funcion o expresion compleja, el nombre de un Array, Esto permite examinar la memoria
quitSale del gdb
run arglistaEjecutar el programa desde el principio con la lista opcional de argumentos de linea de comandos, contenidos en arglista
set variable = expAsigna a una variable del codigo fuente un valor. Esto permite alterar el estado de la memoria
setModifica las variables del entorno de gdb
stepEjecutar el siguiente paso del programa, entrar en cualquier funcion llamada
undisplayCancelar un despliegue
watchCrea un punto de observacion
whatis expDespliega el tipo de datos de exp
Anuncios

En resumen, hoy hemos visto la depuracion, que es, para que sirve, como debemos compilarlo para habilitarlo, la herramienta para trabajar, asi como tambien un ejemplo para ver algunos de los comandos que podemos utilizar. 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
pp258

Donatión

It’s for site maintenance, thanks!

$1.50