Esercizio - Eseguire il debug con Visual Studio Code
È 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.
In Visual Studio Code selezionare File>Apri cartella.
Creare una nuova cartella denominata
DotNetDebuggingin un percorso a scelta. Scegliere quindi Seleziona cartella.Aprire il terminale integrato da Visual Studio Code selezionando Visualizza>terminale dal menu principale.
Copiare e incollare il comando seguente nella finestra del terminale:
dotnet new consoleQuesto comando crea un file Program.cs nella cartella con un programma "Hello World" di base già scritto. Crea anche un file di progetto C# denominato DotNetDebugging.csproj.
Nella finestra del terminale copiare e incollare il comando seguente per eseguire il programma "Hello World".
dotnet runLa finestra del terminale visualizza l'output "Hello World!".
Configurare Visual Studio Code per il debug di .NET
Aprire Program.cs selezionandolo.
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 visualizzato questo prompt, selezionare il pulsante Installa nel prompt.
Visual Studio Code installerà l'estensione C# e visualizzerà un altro prompt per aggiungere gli asset necessari per compilare ed eseguire il debug del progetto. Selezionare il pulsante Sì .
È possibile chiudere la scheda Estensione: C# per concentrarsi sul codice di cui verrà eseguito 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 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...
Aprire Program.cs selezionandolo.
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.
Salvare il file selezionando CTRL+S per Windows e Linux. Selezionare Cmd+S per Mac.
Verrà ora esaminato il funzionamento del codice aggiornato prima del debug. Eseguire il programma immettendo il comando seguente nel terminale:
dotnet run
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
Avviare il programma selezionando la scheda Esegui e debug a sinistra, quindi selezionando il pulsante Avvia debug . Potrebbe essere necessario selezionare prima il pulsante Esegui e debug , quindi selezionare il file Program.cs .
Si noterà che il programma termina rapidamente. Ciò è normale perché non sono ancora stati aggiunti punti di interruzione.
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
Aggiungere un punto di interruzione facendo clic sul margine sinistro alla riga 1 in
int result = Fibonacci(5);.
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().
Controllare lo stato delle variabili
Ora, prendi un po' di tempo per esaminare i valori delle diverse variabili usando il 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,n2esum?
Si passerà quindi al ciclo
forusando il controllo del debugger Passaggio.
Continuare ad avanzare finché non si raggiunge la prima riga all'interno del ciclo
foralla riga:sum = n1 + n2;
Nota
Si noterà che per spostarsi all'interno della riga for(...) {} sono necessari più comandi di esecuzione. Questa situazione 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:
- Il ciclo viene conteggiato da 2 a
n(il numero della sequenza di Fibonacci cercato). - Se
nè minore di 2, il ciclo non verrà mai eseguito. L'istruzionereturnalla fine della funzione restituirà 0 senè 0 e 1 senè 1 o 2. Questi sono i valori 0, primo e secondo nella serie di Fibonacci, per definizione. - 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,n1en2sono i due valori precedenti esumè il valore per l'iterazione corrente. Per questo motivo, ogni volta che si calcola la somma dei due valori precedenti e la si imposta susum, si aggiornano i valorin1en2.
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.
Aggiungere un secondo punto di interruzione nella riga 13.
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.
Ora che è stato impostato un punto di interruzione valido nel ciclo, usa il controllo Continua del debugger per avanzare fino a quando il punto di interruzione non viene raggiunto. Esaminando le variabili locali, è possibile osservare queste righe:
n [int]: 5 n1 [int]: 0 n2 [int]: 1 sum [int]: 1 i [int]: 2Tutte le righe sembrano corrette. La prima volta che viene eseguito il ciclo,
sumdei due valori precedenti è 1. Anziché eseguire ogni singola riga, è possibile usare i punti di interruzione per passare all'esecuzione successiva del ciclo.Selezionare Continua per continuare il flusso del programma fino a quando non viene raggiunto il punto di interruzione successivo, che si troverà nel passaggio successivo del ciclo.
Nota
Non essere troppo preoccupato per 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]: 3Si pensa che questi valori abbiano ancora senso? Sembra di sì. Per il terzo numero di Fibonacci, si prevede che
sumsia uguale a 2 e lo è.Ok, selezionare Continua per ripetere il ciclo.
n [int]: 5 n1 [int]: 1 n2 [int]: 2 sum [int]: 3 i [int]: 4Di nuovo, non viene rilevato alcun errore. Si prevede che il quarto valore della serie sia 3.
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. 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. IdentificatiImpostare 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.
Rimuovere i punti di interruzione precedenti nelle righe 1 e 13. Puoi farlo cliccando sui punti di interruzione 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 Punti di interruzione in basso a sinistra.
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.
Avviare il debugger un'ultima volta.
n [int]: 5 n1 [int]: 2 n2 [int]: 3 sum [int]: 3Il funzionamento non è corretto. È stato specificatamente richiesto Fibonacci(5) e si è ottenuto Fibonacci(4). Questa funzione restituisce
n2e ogni iterazione del ciclo calcola il valoresume impostan2uguale asum.In base a queste informazioni e all'esecuzione del debug precedente, è possibile osservare che il ciclo è terminato quando
iera 4, non 5.Si osservi la prima riga del ciclo
fornel dettaglio.for (int i = 2; i < n; i++)Ciò significa che verrà chiuso non appena nella parte superiore del ciclo for
inon è più inferiore an. Ciò significa che il codice del ciclo non verrà eseguito nel caso in cuiisia uguale an. Sembra che ciò che si voleva fosse continuare l'esecuzione fino ai <= 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; }Se non è già stato fatto, arrestare la sessione di debug.
Quindi apportare la modifica precedente alla riga 10 e lasciare il punto di interruzione nella riga 17.
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]: 5Ecco! Il risultato è stato raggiunto. Ottimo lavoro, hai salvato il giorno per Fibonacci, Inc.!
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. È 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.