Debuggers: qué son y cómo usarlos

Gran parte del tiempo que se dedica al desarrollo de software suele dedicarse a encontrar y de resolver errores en el código, una tarea que puede consumir mucho tiempo y que puede causar mucha frustración. Existen muchas herramientas que facilitan este proceso, pero las más conocidas y usadas son los depuradores, también conocidos en inglés como debuggers.

question

¿Qué es un debugger?

Los debuggers observan el flujo de ejecución del programa que están depurando, y van guardando información del mismo como los valores de las variables o la pila de llamadas del proceso donde se va almacenando las llamadas a los métodos y/o funciones que se han ejecutado… Podemos acceder a esta información de diferentes maneras dependiendo del depurador que usemos, pero en general los debuggers nos proporcionan una o varias formas de ver esa información.

Si habéis investigado sobre debuggers previamente, seguro que el término punto de ruptura ha aparecido más de una vez. Una característica principal de la gran mayoría de debuggers es la posibilidad de parar la ejecución del programa cuando se llegue a un punto que nosotros hemos indicado (la gran mayoría de IDEs con debugger incorporado te dejan seleccionarlo antes de empezar la depuración, otros como gdb tienes que ejecutar primero el debugger). Cuando el programa llegue a ese punto, la ejecución se parará y podremos ver la información que hay en ese momento.

Debuggers
Ejemplo de variables durante una depuración usando PHPStorm

Ese punto donde indicamos que se pare la ejecución es lo que se denomina punto de ruptura, o breakpoint en inglés. El debugger detectará que en esa línea hay un punto de ruptura y cuando llegue a esa línea se parará la ejecución. Aquí es cuando entra otra de las funcionalidades de los debuggers, la función single-stepping.

Los debuggers nos permiten que, en lugar de dejar que el código se ejecute hasta el final, ir línea por línea de tal manera que podemos controlar la ejecución del código al ritmo que deseamos. Esto es útil cuando queremos saber, por ejemplo, qué valor tiene una variable antes de un punto en concreto y ver si ese valor es lo que esperamos, o si en un flujo condicional sigue el camino que deseamos que siga.

Ahora bien, imaginemos que tenemos el siguiente snippet de código en C.

#include <stdio.h>

int sum(int a, int b) {
    return a + b;
}
int main() {
    printf("hello world");
    int c = sum(4,2);
    return 0;
}

Si vamos paso a paso en la depuración del código, veremos cómo pasamos de la línea donde se declara la variable c pero no hemos entrado dentro de la función sum. Por defecto, cuando vamos a paso a paso en la depuración el depurador pasa por las funciones pero no llega a entrar en ellas. Para poder entrar en las funciones en lugar de un step hay que hacer un step-into. De esta manera podremos entrar dentro de las funciones y ver paso a paso cómo se ejecutan. De la misma manera si estamos dentro de una función pero queremos salir de ésta para volver al flujo tenemos la opción de step-out que nos permite volver al punto donde se ejecutó la función.

Depuradores más conocidos

El depurador estándar de GNU, gdb, es un debugger muy utilizado en entornos Unix. Sin interfaz gráfica de usuario, permite trazar la ejecución del programa y acceder a la tabla de símbolos del proceso para así depurar el código y poder analizarlo.

Normalmente la gran mayoría de IDEs (Eclipse, toda la familia Jetbrains…) llevan un debugger incorporado el cual permite la depuración de forma más amistosa que gdb. Navegadores como Firefox o Google Chrome tienen un debugger en las herramientas de desarrollador que permiten poder depurar nuestras aplicaciones web de la misma manera que podemos depurar programas escritos en otro lenguaje.

Ventajas de los debuggers

Seguramente te habrás preguntado qué te puede aportar un debugger que no te aporte añadir un console.log o un print en tu programa. Si bien puede parecer que usar prints es mucho más fácil y rápido que depurar usando debuggers, las ventajas que aportan estas herramientas son muchas y nada despreciables, a destacar:

  • Mayor control: podemos controlar el flujo de ejecución para adaptarlo a nuestras necesidades
  • Mayor cantidad de información: Desde valores de variables hasta métodos ejecutados…
  • No hay que modificar el código: Cuando añadimos un print modificamos nuestro código. La depuración en ningún momento modifica el código, lo cual hace que la información que muestra la herramienta represente el estado de la aplicación.

Conclusiones

Saber cómo usar un debugger correctamente hace que la detección y corrección de errores se agilice, además de que, si bien al principio pueden ser unas herramientas un tanto complejas para entender su potencial y aprovecharlo al máximo, una vez su uso ha sido interiorizado se convierten en una herramienta imprescindible para cualquier desarrollador.

Backend

Picture of Samuel Sánchez

Samuel Sánchez

Meditación zen como camino a la calma tras desplegar en producción
Picture of Samuel Sánchez

Samuel Sánchez

Meditación zen como camino a la calma tras desplegar en producción

We are HIRING!

What Can We Do