Esercizio - Eseguire il debug con Visual Studio

Completato

È il momento di mettere in pratica le conoscenze appena acquisite sul processo di debug. È il tuo primo giorno di lavoro e vuoi mettere in pratica le tue competenze di debug .NET per correggere un bug nel prodotto di punta dell'azienda, un calcolatore di Fibonacci.

Creare un progetto .NET di esempio per il debug

Per configurare il debug di Visual Studio per .NET, è necessario prima di tutto un progetto .NET. Visual Studio offre molti modelli di avvio che semplificano la creazione di un nuovo progetto.

  1. In Visual Studio selezionare File>Nuovo>Progetto.

  2. Nella finestra di dialogo Crea un nuovo progetto selezionare App console e scegliere Avanti.

  3. Assegnare al progetto il nome DotNetDebugging e scegliere la posizione in cui salvarlo. Lasciare invariati i valori predefiniti per tutte le altre impostazioni e quindi selezionare Avanti.

  4. Selezionare Crea nella schermata finale.

Visual Studio crea automaticamente il progetto Console usando il modello selezionato. Dopo aver caricato il progetto, aprire Program.cs selezionandolo.

Aggiungere la logica del programma di Fibonacci

Il progetto corrente scrive un messaggio "Hello World" nella console e non offre molti elementi di cui eseguire il debug. Si userà invece un breve programma .NET per calcolare il numero N della sequenza di Fibonacci.

La sequenza di Fibonacci è una successione di numeri che inizia con 0 e 1, in cui ogni altro numero che segue è la somma dei due precedenti. La sequenza continua come illustrato di seguito:

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

Il codice di esempio seguente contiene un bug, quindi usiamo gli strumenti di debug di Visual Studio per diagnosticare e risolvere il problema.

  1. Sostituire il contenuto di Program.cs con il codice seguente:
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

Questo codice contiene un errore di debug più avanti in questo modulo. Non è consigliabile usarlo in tutte le applicazioni di Fibonacci critiche fino a quando non viene risolto il bug.

  1. Salvare il file con CTRL+S per Windows e Linux. Selezionare CMD+S per Mac.

  2. Verrà ora esaminato il funzionamento del codice aggiornato prima del debug. Eseguire il programma premendo il pulsante di avvio verde nella barra dei comandi di Visual Studio.

  3. Alla fine dell'output della console di debug, è possibile vedere che il programma scrive 3 nella console e quindi viene chiuso con il codice 0. In genere, il codice di uscita 0 del programma indica che il programma è stato eseguito e terminato senza arresti anomali. Tuttavia, esiste una differenza tra l'arresto anomalo e la restituzione del valore corretto.

Finestra del terminale con l'output del programma modificato.

In questo caso, è stato richiesto al programma di calcolare il quinto valore della sequenza di Fibonacci:

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

Il quinto valore dell'elenco è 5, ma il programma ha restituito 3. Usare il debugger per diagnosticare e correggere questo errore.

Usare i punti di interruzione e l'esecuzione un'istruzione alla volta

  1. Aggiungere un punto di interruzione facendo clic sul margine sinistro alla riga 1, in corrispondenza di int result = Fibonacci(5);.

  2. Avviare di nuovo il debug. Viene avviata l'esecuzione del programma. Si interrompe (sospende l'esecuzione) alla riga 1 a causa del punto di interruzione impostato. Usare i controlli del debugger per eseguire l'istruzione nella funzione Fibonacci().

    Screenshot del pulsante Eseguire l'istruzione.

Controllare lo stato delle variabili

Esaminare i diversi valori delle variabili usando la finestra Variabili locali.

Screenshot del riquadro Variabili locali.

  • Qual è il valore visualizzato per il parametro n?
  • All'inizio dell'esecuzione della funzione quali sono i valori per le variabili locali n1, n2 e sum?
  1. Si passerà quindi al ciclo for usando il controllo del debugger Esegui istruzione/routine.

    Screenshot del pulsante Passaggio.

  2. Continuare ad avanzare fino a raggiungere la prima riga all'interno del ciclo for. La riga che recita:

    sum = n1 + n2;
    

Nota

È possibile notare che per spostarsi nella for(...) {} riga sono necessari più passaggi nei comandi. Ciò si verifica perché in questa riga sono presenti più istruzioni. Quando si esegue l'istruzione, si passa all'istruzione successiva nel codice. In genere, è presente una sola istruzione per riga. In caso contrario, sono necessari più passaggi per passare alla riga successiva.

Pensare al codice

Una parte importante del processo di debug consiste nell'ipotizzare in base alle informazioni le operazioni che le parti del codice (funzioni e blocchi, ad esempio i cicli) stanno tentando di eseguire. Nel processo di debug è normale non avere alcuna certezza. Ma essere attivamente impegnati nel processo di debug consente di individuare i bug molto più rapidamente.

Prima di approfondire, tenere presente che la sequenza di Fibonacci è una serie di numeri che inizia con 0 e 1, in cui ogni altro numero che segue è la somma dei due precedenti.

Ciò significa che:

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)

Comprendendo questa definizione ed esaminando questo ciclo for, è possibile dedurre che:

  1. Il ciclo viene conteggiato da 2 a n (il numero della sequenza di Fibonacci cercato).
  2. Se n è minore di 2, il ciclo non viene mai eseguito. L'istruzione return alla fine della funzione restituisce 0 se n è 0 e 1 se n è 1 o 2. Questi valori sono i valori zero, primo e secondo nella serie di Fibonacci, per definizione.
  3. Il caso più interessante si verifica quando n è maggiore di 2. In questi casi, il valore corrente viene definito come la somma dei due valori precedenti. Di conseguenza per questo ciclo, n1 e n2 sono i due valori precedenti e sum è il valore per l'iterazione corrente. A causa di questa logica, ogni volta che si calcola la somma dei due valori precedenti e lo si imposta su sum, si aggiornano i n1 valori e n2 .

Ora che questi concetti sono chiari, è possibile passare al debugger. Tuttavia, può essere utile esaminare il codice per verificare se esegue le operazioni previste e ottenere altre informazioni in caso contrario.

Individuare il bug con i punti di interruzione

Eseguire un'istruzione alla volta nel codice può essere utile ma noioso, Soprattutto quando si usano cicli o altro codice che viene chiamato ripetutamente. Anziché eseguire più volte il ciclo un'istruzione alla volta, è possibile impostare un nuovo punto di interruzione nella prima riga del ciclo.

È importante avere una strategia sulle posizioni in cui inserire i punti di interruzione. Il valore di sum è particolarmente interessante poiché rappresenta il valore massimo corrente di Fibonacci. Per questo motivo, inserire il punto di interruzione nella riga dopo l'impostazione di sum.

  1. Aggiungere un secondo punto di interruzione nella riga 14.

    Screenshot che mostra un secondo punto di interruzione impostato.

    Nota

    Se si nota che si continua a eseguire il codice e quindi si esegue una riga o due, è possibile aggiornare facilmente i punti di interruzione in righe più efficienti.

  2. Dopo aver impostato un punto di interruzione valido nel ciclo, selezionare Continua nei controlli del debugger per avanzare fino a quando non viene raggiunto il punto di interruzione. Esaminando le variabili locali, è possibile osservare queste righe:

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

    Tutte le righe sembrano corrette. La prima volta che viene eseguito il ciclo, sum dei due valori precedenti è 1. Anziché eseguire ogni singola riga, è possibile usare i punti di interruzione per passare all'esecuzione successiva del ciclo.

  3. Selezionare Continua per continuare il flusso del programma fino a quando non viene raggiunto il punto di interruzione successivo, che si troverà al passaggio successivo del ciclo.

    Nota

    Non preoccuparsi di ignorare il bug quando si usa Continua. È consigliabile aspettarsi che sia possibile eseguire il debug tramite il codice più volte per trovare il problema. Spesso è più veloce eseguirlo alcune volte anziché essere troppo cauti durante l'esecuzione delle istruzioni.

    In questo caso, si osservano i valori seguenti:

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

    questi valori abbiano ancora senso? Sembra di sì. Per il terzo numero di Fibonacci, si prevede che sum sia uguale a 2 e lo è.

  4. Selezionare Continua per eseguire di nuovo il ciclo.

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

    Il risultato è corretto. Si prevede che il quarto valore della serie sia 3.

  5. A questo punto, è possibile iniziare a chiedersi se il codice è sempre stato corretto e si è solo immaginato il bug. Si esegua nuovamente il ciclo per l'ultima volta. Selezionare Continua ancora una volta.

    Il programma è terminato e l'output è 3! Il risultato non è corretto.

    Si è scoperto che il codice viene eseguito correttamente nel ciclo fino a quando i è uguale a 4, ma termina prima di calcolare il valore finale. Abbiamo ristretto il campo in cui si trova il bug.

  6. Impostare un altro punto di interruzione nella riga 18 seguente:

    return n == 0 ? n1 : n2;
    

    Questo punto di interruzione consente di controllare lo stato del programma prima che la funzione venga chiusa. Poiché sono già noti tutti gli elementi che è possibile prevedere dai punti di interruzione precedenti nelle righe 1 e 13, è possibile cancellarli.

  7. Rimuovere i punti di interruzione precedenti nelle righe 1 e 13. Selezionare i punti di interruzione nel margine accanto ai numeri di riga oppure deselezionare le caselle di controllo dei punti di interruzione per le righe 1 e 13 nel riquadro punti di interruzione in basso a sinistra.

    Screenshot che mostra i punti di interruzione elencati nel riquadro dei punti di interruzione.

    Ora che comprendiamo meglio cosa sta succedendo, possiamo impostare un punto di interruzione progettato per intercettare il programma mentre si comporta in modo errato. Ora dovremmo essere in grado di rilevare questo bug!

  8. Avviare il debugger un'ultima volta.

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

    È stato specificatamente richiesto Fibonacci(5) e si è ottenuto Fibonacci(4), che non è corretto. Questa funzione restituisce n2 e ogni iterazione del ciclo calcola il valore sum e imposta n2 uguale a sum.

    In base a queste informazioni e all'esecuzione del debug precedente, è possibile osservare che il ciclo è terminato quando i era 4, non 5.

    Esaminiamo l'istruzione for del ciclo un po' più da vicino.

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

    Questa logica fa sì che il programma termini non appena la sommità del ciclo vede che i uguale a n. Ciò significa che il codice del ciclo non viene eseguito per il caso in cui i è uguale a n. Sembra che ciò che si voleva fosse continuare l'esecuzione fino a i <= n, invece:

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

    Con questa modifica, il programma aggiornato sarà simile all'esempio seguente:

    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. Se non è già stato fatto, arrestare la sessione di debug.

  10. Apportare la modifica precedente alla riga 11 e lasciare il punto di interruzione nella riga 18.

  11. Riavviare il debugger. Questa volta, quando si raggiunge il punto di interruzione alla riga 18, vengono visualizzati i valori seguenti:

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

    Ehi! Il risultato è stato raggiunto. Ottimo lavoro, hai salvato il giorno per Fibonacci, Inc.!

  12. Selezionare Continua, solo per assicurarsi che il programma restituisca il valore corretto.

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

    E che restituisca l'output corretto.

L'operazione è stata completata. Hai eseguito il debug di codice che non hai scritto usando il debugger .NET in Visual Studio.

Nell'unità successiva si apprenderà come semplificare il debug del codice usando le funzionalità di registrazione e traccia integrate in .NET.