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
DotNetDebugging
in un percorso a scelta. Scegliere quindi Seleziona cartella.Aprire il terminale integrato da Visual Studio Code selezionando Visualizza>Terminale nel menu principale.
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.
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
Per aprire Program.cs, selezionarlo.
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.
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 Sì.
È 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...
Per aprire Program.cs, selezionarlo.
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, e selezionando poi il pulsante Avvia debug. Potrebbe essere necessario selezionare prima il pulsante Esegui con debug e quindi 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 corrispondenza di
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
Esaminare i diversi valori delle 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
,n2
esum
?
Si passerà quindi al ciclo
for
usando il controllo del debugger Esegui istruzione/routine.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:
- 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'istruzionereturn
alla 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,n1
en2
sono 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 valorin1
en2
.
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.
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.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 è.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.
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. 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. È 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.
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]: 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 valoresum
e impostan2
uguale asum
.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 an
. Ciò significa che il codice del ciclo non verrà eseguito nel caso in cuii
sia 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]: 5
Questo Il risultato è stato raggiunto. Ottimo lavoro, Fibonacci, Inc. è stata salvata.
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.