Esercizio - Eseguire il debug con Visual Studio Code

Completato

È il momento di mettere in pratica le conoscenze appena acquisite sul processo di debug. È il primo giorno che si lavora sul progetto ed è il momento di applicare le proprie competenze sul debug di .NET correggendo un bug nel prodotto di punta dell'azienda, un calcolatore di Fibonacci.

Creare un progetto .NET di esempio per il debug

Per configurare Visual Studio Code per il debug di .NET, è necessario innanzitutto un progetto .NET. Visual Studio Code include un terminale integrato, che semplifica la creazione di un nuovo progetto.

  1. In Visual Studio Code selezionare File>Apri cartella.

  2. Creare una nuova cartella denominata DotNetDebugging in un percorso a scelta. Scegliere quindi Seleziona cartella.

  3. Aprire il terminale integrato da Visual Studio Code selezionando Visualizza>Terminale nel menu principale.

  4. Copiare e incollare il comando seguente nella finestra del terminale:

    dotnet new console
    

    Questo comando crea un file Program.cs nella cartella con un programma "Hello World" di base già scritto. Crea inoltre file di progetto C# denominato DotNetDebugging.csproj.

  5. Nella finestra del terminale copiare e incollare il comando seguente per eseguire il programma "Hello World".

    dotnet run
    

    La finestra del terminale visualizza l'output "Hello World!".

Configurare Visual Studio Code per il debug di .NET

  1. Per aprire Program.cs, selezionarlo.

  2. Quando si apre un file C# in Visual Studio Code per la prima volta, viene visualizzata la richiesta di installare le estensioni consigliate per C#. Se viene visualizzata questa richiesta, selezionare il pulsante Installa nella richiesta.

    Screenshot della richiesta di Visual Studio Code di installare l'estensione C#.

  3. Visual Studio Code installa l'estensione C# e visualizza un'altra richiesta per aggiungere gli asset necessari per la compilazione e il debug del progetto. Selezionare il pulsante .

    Screenshot della richiesta di Visual Studio Code di aggiungere asset necessari per compilare ed eseguire il debug del progetto .NET.

  4. È possibile chiudere la scheda Extension: C# per concentrarsi sul codice di cui eseguire il debug.

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 l'Nesimo numero 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...
  1. Per aprire Program.cs, selezionarlo.

  2. Sostituire il contenuto di Program.cs con il codice seguente:

    int result = Fibonacci(5);
    Console.WriteLine(result);
    
    static int Fibonacci(int n)
    {
        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 cui verrà eseguito il debug più avanti in questo modulo. Non è consigliabile usarlo in tutte le applicazioni di Fibonacci critiche fino a quando non viene risolto il bug.

  3. Salvare il file selezionando CTRL+S per Windows e Linux. Selezionare CMD+S per Mac.

  4. Verrà ora esaminato il funzionamento del codice aggiornato prima del debug. Eseguire il programma immettendo il comando seguente nel terminale:

    dotnet run
    

    Finestra del terminale con l'output del programma modificato.

  5. Il risultato, 3, viene visualizzato nell'output del terminale. Quando si consulta questo grafico della sequenza di Fibonacci che mostra la posizione della sequenza in base zero per ogni valore tra parentesi, si noterà che il risultato sarà 5. Acquisire familiarità con il debugger e correggere il programma.

    0 (0), 1 (1), 1 (2), 2 (3), 3 (4), 5 (5), 8 (6), 13 (7), 21 (8)...
    

Analizzare i problemi

  1. Avviare il programma selezionando la scheda Esegui e debug a sinistra, e selezionando poi il pulsante Avvia debug. Potrebbe essere necessario selezionare prima il pulsante Esegui con debug e quindi il file Program.cs.

    Screenshot del pulsante Avvia debug in Visual Studio Code.

    Si noterà che il programma termina rapidamente. Ciò è normale perché non sono ancora stati aggiunti punti di interruzione.

  2. Se la console di debug non viene visualizzata, selezionare CTRL+MAIUSC+Y per Windows e Linux o Cmd+MAIUSC+Y per Mac. Verranno visualizzate diverse righe di informazioni di diagnostica, seguite da queste righe alla fine:

    ...
    Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.0\System.Threading.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.0\System.Text.Encoding.Extensions.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    3
    The program '[88820] DotNetDebugging.dll' has exited with code 0 (0x0).
    

Le linee nella parte superiore indicano che le impostazioni di debug predefinite abilitano l'opzione "Just My Code". Questo significa che il debugger eseguirà solo il debug del codice e non eseguirà l'istruzione nel codice sorgente per .NET, a meno che questa modalità non venga disabilitata. Questa opzione consente di concentrarsi sul debug del codice.

Alla fine dell'output della console di debug il programma scrive 3 nella console, quindi termina 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. In questo caso, è stato richiesto al programma di calcolare il quinto valore della sequenza di Fibonacci:

0 (0), 1 (1), 1 (2), 2 (3), 3 (4), 5 (5), 8 (6), 13 (7), 21 (8)...

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);.

    Screenshot della posizione del punto di interruzione nel codice.

  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 Esegui istruzione.

Controllare lo stato delle variabili

Esaminare i diversi valori delle variabili usando il pannello Variabili.

Screenshot del pannello Variabili.

  • 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 Esegui istruzione/routine.

  2. Continuare ad avanzare finché non si raggiunge la prima riga all'interno del ciclo for alla riga:

    sum = n1 + n2;
    

Nota

Si noterà che per spostarsi all'interno della riga for(...) {} sono necessari più comandi di esecuzione. 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. Tuttavia, essere coinvolti attivamente nel processo di debug consentirà di individuare i bug in modo molto più rapido.

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 verrà mai eseguito. L'istruzione return alla fine della funzione restituirà 0 se n è 0 e 1 se n è 1 o 2. Questi sono i valori 0, 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. Per questo motivo, ogni volta che si calcola la somma dei due valori precedenti e la si imposta su sum, si aggiornano i valori n1 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

L'esecuzione dettagliata del codice può essere utile ma noiosa, soprattutto quando si lavora con i cicli o un altro codice chiamato ripetutamente. Anziché eseguire più volte il ciclo un'istruzione alla volta, è possibile impostare un nuovo punto di interruzione nella prima riga del ciclo.

Quando si esegue questa operazione, è 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 13.

    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, usare il controllo del debugger Continua 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. È necessario prevedere che spesso si eseguirà il debug del codice più volte per individuare 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
    

    Si pensa che 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
    

    Di nuovo, non viene rilevato alcun errore. 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.

    Attendere un minuto. L'esecuzione del programma è terminata ed è stato restituito 3. Questo non è corretto.

    Non preoccuparsi. Non si tratta di un fallimento, ma di una lezione. 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. È ora possibile iniziare a ipotizzare la posizione del bug. Identificati

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

    return n == 0 ? n1 : n2;
    

    Questo punto di interruzione consente di esaminare lo stato del programma prima del termine della funzione. 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. È possibile eliminarli facendo clic su di essi nel margine accanto ai numeri di riga oppure deselezionando le caselle di controllo dei punti di interruzione per le righe 1 e 13 nel riquadro dei punti di interruzione in basso a sinistra.

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

    Dopo aver compreso meglio cosa sta succedendo e aver impostato un punto di interruzione progettato per intercettare il programma in errore, sarà possibile individuare il bug.

  8. Avviare il debugger un'ultima volta.

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

    Il funzionamento non è corretto. È stato specificatamente richiesto Fibonacci(5) e si è ottenuto Fibonacci(4). 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.

    Si osservi la prima riga del ciclo for nel dettaglio.

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

    Ciò significa che verrà chiuso non appena nella parte superiore del ciclo for i non è più inferiore a n. Ciò significa che il codice del ciclo non verrà eseguito nel caso in cui i sia 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)
    {
        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. Quindi apportare la modifica precedente alla riga 10 e lasciare il punto di interruzione nella riga 17.

  11. Riavviare il debugger. In questo caso, quando si raggiunge il punto di interruzione nella riga 17, verranno visualizzati i valori seguenti:

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

    Questo Il risultato è stato raggiunto. Ottimo lavoro, Fibonacci, Inc. è stata salvata.

  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.

Ce l'hai fatta! È stato eseguito il debug di codice non scritto, usando il debugger .NET in Visual Studio Code.

Nell'unità successiva si apprenderà come rendere più semplice il debug del codice, usando le funzionalità di registrazione e analisi integrate in .NET.