Ejercicio: depuración con Visual Studio

Completado

Es el momento de poner en práctica todo lo que acaba de aprender sobre depuración. Es su primer día del trabajo, y quiere poner en práctica sus conocimientos sobre la depuración de .NET corrigiendo un error en el producto insignia de la empresa, una calculadora de Fibonacci.

Creación de un proyecto de .NET de ejemplo para la depuración

Para configurar Visual Studio para la depuración de .NET, primero necesitamos un proyecto de .NET. Visual Studio proporciona una gran cantidad de plantillas de inicio que facilita la creación de un nuevo proyecto.

  1. En Visual Studio, seleccione Archivo > Nuevo >proyecto .

  2. En el cuadro de diálogo Crear un proyecto, seleccione Aplicación de consola y elija Siguiente.

  3. Asigne al proyecto el nombre DotNetDebugging y elija la ubicación donde desea guardar. Deje el resto de opciones en sus valores predeterminados y, luego, seleccione Siguiente.

  4. Seleccione Crear en la pantalla final.

Visual Studio crea el proyecto de consola para nosotros mediante la plantilla que hemos seleccionado. Una vez que se cargue el proyecto, seleccione Program.cs para abrirlo.

Adición de la lógica del programa de Fibonacci

Nuestro proyecto actual escribe un mensaje "Hola mundo" en la consola, lo que no nos proporciona mucho para depurar. En su lugar, vamos a usar un programa .NET corto para calcular el número Nº de la secuencia de Fibonacci.

La secuencia de Fibonacci es un conjunto de números que empiezan por el 0 y el 1, y cada uno de los siguientes es la suma de los dos anteriores. La secuencia continúa así:

0, 1, 1, 2, 3, 5, 8, 13, 21...

El código de ejemplo siguiente contiene un error, por lo que vamos a usar las herramientas de depuración de Visual Studio para diagnosticar y resolver el problema.

  1. Reemplace el contenido de Program.cs por el código siguiente:
int result = Fibonacci(5);
Console.WriteLine(result);

static int Fibonacci(int n)
{
    Console.WriteLine("The output is: ");
    int n1 = 0;
    int n2 = 1;
    int sum;

    for (int i = 2; i < n; i++)
    {
        sum = n1 + n2;
        n1 = n2;
        n2 = sum;
    }

    return n == 0 ? n1 : n2;
}

Nota

Este código contiene un error que depuramos más adelante en este módulo. No se recomienda usarlo en las aplicaciones de Fibonacci críticas hasta que se solucione el error.

  1. Presione CTRL+S para guardar el archivo en Windows y Linux. En equipos Mac, presione Cmd+S.

  2. Echemos un vistazo a cómo funciona el código actualizado antes de depurarlo. Ejecute el programa presionando el botón de inicio verde en la barra de comandos de Visual Studio.

  3. Al final de la salida de la consola de depuración, puede ver que el programa escribe 3 en la consola y, luego, se cierra con el código 0. Normalmente, el código 0 de salida del programa indica que el programa se ejecutó y se cerró sin bloqueos. Sin embargo, hay una diferencia entre que no se bloquee y que se devuelva el valor correcto.

Ventana de terminal con salida de programa modificada.

En este caso, pedimos al programa que calculara el quinto valor de la secuencia de Fibonacci:

0, 1, 1, 2, 3, 5, 8, 13, 21...

El quinto valor de esta lista es 5, pero el programa devolvió 3. Vamos a usar el depurador para diagnosticar y corregir este error.

Uso de puntos de interrupción y de la ejecución paso a paso

  1. Para agregar un punto de interrupción, haga clic en el margen izquierdo de la línea 1 en int result = Fibonacci(5);.

  2. Vuelva a iniciar la depuración. El programa comenzará a ejecutarse Se interrumpirá (pausará la ejecución) en la línea 1 debido al punto de interrupción establecido. Use los controles del depurador para depurar paso a paso por instrucciones la función Fibonacci().

    Captura de pantalla del botón Paso a paso.

Comprobación del estado de las variables

Ahora, dedique tiempo a inspeccionar los valores de las diferentes variables mediante la ventana Locales.

Captura de pantalla del panel Variables locales.

  • ¿Cuál es el valor que se muestra para el parámetro n?
  • Al principio de la ejecución de la función, ¿cuáles son los valores de las variables locales n1, n2 y sum?
  1. A continuación, avanzamos al bucle for mediante el control del depurador Paso a paso.

    Captura de pantalla del botón Paso a paso por encima.

  2. Continúe avanzando hasta llegar a la primera línea dentro del for bucle. Línea que lee:

    sum = n1 + n2;
    

Nota

Es posible que observe que para desplazarse por la for(...) {} línea es necesario realizar varios pasos en los comandos. Esta situación se produce porque en esta línea hay varias instrucciones. Al realizar una depuración paso a paso, se pasa a la siguiente instrucción del código. Normalmente, hay una instrucción por línea. Si no es así, se necesitan varios pasos para ir a la línea siguiente.

Reflexión sobre el código

Una parte importante de la depuración es detenerse y hacer algunas suposiciones fundamentadas sobre lo que cree que las partes del código (funciones y bloques, como los bucles) intentan hacer. No pasa nada si no está seguro, esa incertidumbre forma parte del proceso de depuración. Pero estar activamente involucrado en el proceso de depuración le ayuda a localizar errores mucho más rápidamente.

Antes de profundizar más, recuerde que la secuencia de Fibonacci es una serie de números que comienzan por el 0 y el 1, y cada uno de los números siguientes es la suma de los dos anteriores.

Esto significa que:

Fibonacci(0) = 0
Fibonacci(1) = 1
Fibonacci(2) = 1 (0 + 1)
Fibonacci(3) = 2 (1 + 1)
Fibonacci(4) = 3 (1 + 2)
Fibonacci(5) = 5 (2 + 3)

Si entendemos esa definición y examinamos este bucle for, podemos deducir que:

  1. El bucle cuenta de 2 a n (el número de secuencia de Fibonacci que buscamos).
  2. Si n es menor que 2, el bucle nunca se ejecuta. La return instrucción al final de la función devuelve 0 si n es 0 y 1 si n es 1 o 2. Estos valores son los valores cero, primero y segundo de la serie Fibonacci, por definición.
  3. El caso más interesante es cuando n es mayor que 2. En esos casos, el valor actual se define como la suma de los dos valores anteriores. Por lo tanto, para este bucle, n1 y n2 son los dos valores anteriores y sum es el valor de la iteración actual. Debido a esta lógica, cada vez que averiguamos la suma de los dos valores anteriores y la establecemos en sum, actualizamos nuestros valores de n1 y n2.

Bien, no es necesario seguir dándole más vueltas a ello; podemos apoyarnos un poco en el depurador. Pero merece la pena pensar en el código para ver si hace lo que esperamos y tener más información para cuando no lo haga.

Detección del error con puntos de interrupción

Aunque la ejecución paso a paso del código puede ser útil, también puede resultar tediosa, Especialmente cuando se trabaja con bucles u otro código al que se llama repetidamente. En lugar de ejecutar paso a paso el bucle una y otra vez, podemos establecer un nuevo punto de interrupción en la primera línea del bucle.

Es importante saber dónde colocar estratégicamente nuestros puntos de interrupción. Nos interesa especialmente el valor de sum, ya que representa el valor máximo actual de Fibonacci. Así, vamos a colocar el punto de interrupción en la línea después de establecer sum.

  1. Agregue un segundo punto de interrupción en la línea 14.

    Captura de pantalla que muestra un segundo punto de interrupción que se establece.

    Nota

    Si observa que el código sigue funcionando y, luego, ejecuta una línea o dos, puede actualizar fácilmente los puntos de interrupción a líneas más eficaces.

  2. Ahora que tenemos un buen punto de interrupción establecido en el bucle, seleccione Continuar en los controles del depurador para avanzar hasta que se alcance el punto de interrupción. Si observamos nuestras variables locales, vemos las siguientes líneas:

    n [int]: 5
    n1 [int]: 0
    n2 [int]: 1
    sum [int]: 1
    i [int]: 2
    

    Todas estas líneas parecen correctas. La primera vez a través del bucle, el valor sum de los dos valores anteriores es 1. En lugar de recorrer línea a línea, podemos aprovechar nuestros puntos de interrupción para saltar a la siguiente vez a través del bucle.

  3. Seleccione Continuar para continuar el flujo del programa hasta llegar al siguiente punto de interrupción, que estará en el siguiente paso a través del bucle.

    Nota

    No se preocupe demasiado por omitir el error al usar Continuar. Deberías esperar que podrías depurar el código varias veces para encontrar el problema. Por lo que a menudo es más rápido recorrerlo varias veces que ser demasiado precavido cuando lo ejecute paso a paso.

    Esta vez, vemos los valores siguientes:

    n [int]: 5
    n1 [int]: 1
    n2 [int]: 1
    sum [int]: 2
    i [int]: 3
    

    ¿Estos valores siguen teniendo sentido? Parece que sí. Para el tercer número de Fibonacci, esperamos ver que sum es igual a 2, y así es.

  4. SeleccioneContinuar para volver a crear un bucle.

    n [int]: 5
    n1 [int]: 1
    n2 [int]: 2
    sum [int]: 3
    i [int]: 4
    

    El resultado es correcto. Se espera que el cuarto valor de la serie sea 3.

  5. Llegados a este punto, podría empezar a preguntarse si el código estaba realmente bien y se ha imaginado el error. Vamos a seguir con él por última vez a través del bucle. Seleccione Continuar una vez más.

    El programa terminó de ejecutarse y la salida es 3. El resultado es incorrecto.

    Ahora sabemos que el código se ejecuta correctamente a través del bucle hasta i que es igual a 4, pero después se cierra antes de calcular el valor final. Hemos acotado dónde está el fallo.

  6. Vamos a establecer un punto de interrupción más en la línea 18, que dice:

    return n == 0 ? n1 : n2;
    

    Este punto de interrupción nos permite inspeccionar el estado del programa antes de que se cierre la función. Ya hemos aprendido todo lo que podemos esperar de nuestros puntos de interrupción anteriores en las líneas 1 y 13, así que podemos borrarlos.

  7. Quite los puntos de interrupción anteriores de las líneas 1 y 13. Seleccione los puntos de interrupción en el margen situado junto a los números de línea, o desmarque las casillas de puntos de interrupción de las líneas 1 y 13 en el panel de puntos de interrupción en la parte inferior izquierda.

    Captura de pantalla que muestra los puntos de interrupción enumerados en el panel puntos de interrupción.

    Ahora que entendemos mejor lo que está pasando y establecemos un punto de interrupción diseñado para detectar nuestro programa en el momento en que se comporta incorrectamente. Ahora deberíamos poder detectar este error.

  8. Inicie el depurador una última vez.

    n [int]: 5
    n1 [int]: 2
    n2 [int]: 3
    sum [int]: 3
    

    Hemos pedido específicamente Fibonacci(5) y hemos recibido Fibonacci(4), que es incorrecto. Esta función devuelve n2, y cada iteración del bucle calcula el valor sum y establece n2 igual a sum.

    En función de esta información y de la ejecución de depuración anterior, podemos ver que el bucle se cerró cuando i era 4, no 5.

    Echemos un vistazo a nuestra instrucción for de bucle un poco más cerca.

    for (int i = 2; i < n; i++)
    

    Esta lógica provoca que el programa se detenga en cuanto el inicio del bucle for detecta que i es igual a n. Esto significa que el código de bucle no se ejecuta en el caso cuando i es igual a n. Parece que nos gustaría que se ejecutara mejor hasta i <= n:

    for (int i = 2; i <= n; i++)
    

    Por lo tanto, con ese cambio, el programa actualizado debería tener un aspecto similar al de este ejemplo:

    int result = Fibonacci(5);
    Console.WriteLine(result);
    
    static int Fibonacci(int n)
    {
        Console.WriteLine("The output is: ");
        int n1 = 0;
        int n2 = 1;
        int sum;
    
        for (int i = 2; i <= n; i++)
        {
            sum = n1 + n2;
            n1 = n2;
            n2 = sum;
        }
    
        return n == 0 ? n1 : n2;
    }
    
  9. Detenga la sesión de depuración si aún no lo ha hecho.

  10. Haga el cambio anterior en la línea 11 y deje nuestro punto de interrupción en la línea 18.

  11. Reinicie el depurador. Esta vez, cuando alcanzamos el punto de interrupción en la línea 18, vemos los siguientes valores:

    n [int]: 5
    n1 [int]: 3
    n2 [int]: 5
    sum [int]: 5
    

    ¡Hola! Parece que lo hemos conseguido. ¡Gran trabajo, salvaste el día para Fibonacci, Inc.!

  12. Seleccione Continuar solo para asegurarse de que el programa devuelve el valor correcto.

    5
    The program '[105260] DotNetDebugging.dll' has exited with code 0 (0x0).
    

    Y que devuelve la salida correcta.

¡Lo ha logrado! Ha depurado código que no ha escrito mediante el depurador de .NET en Visual Studio.

En la unidad siguiente, aprenderá a facilitar la depuración del código mediante las características de registro y seguimiento integradas en .NET.