Esercizio - Monitorare le variabili e il flusso di esecuzione

Completato

La visualizzazione RUN AND DEBUG offre agli sviluppatori un modo semplice per monitorare variabili ed espressioni, osservare il flusso di esecuzione e gestire i punti di interruzione durante il processo di debug.

Esaminare le sezioni della visualizzazione Esegui ed Esegui debug

Ogni sezione della visualizzazione RUN AND DEBUG offre funzionalità univoche. L'uso di una combinazione di queste sezioni durante il processo di debug è spesso utile.

Sezione VARIABLES

Il monitoraggio dello stato della variabile è un aspetto importante del debug del codice. Le modifiche impreviste nello stato della variabile spesso consentono di identificare gli errori logici nel codice.

La sezione VARIABLES organizza le variabili in base all'ambito. L'ambito Locals visualizza le variabili nell'ambito corrente (il metodo corrente).

Annotazioni

La sezione delle istruzioni di primo livello di un'applicazione console è considerata il proprio metodo. Metodo denominato Main.

È possibile espandere (espandere) gli ambiti visualizzati selezionando la freccia a sinistra del nome dell'ambito. È anche possibile espandere variabili e oggetti. Lo screenshot seguente mostra la numbers matrice espansa nell'ambito Locals .

Screenshot che mostra una variabile aperta nella sezione Variabili della visualizzazione Esegui e debug.

È anche possibile modificare il valore di una variabile in fase di esecuzione usando la sezione VARIABLES. È possibile fare doppio clic sul nome della variabile e quindi immettere un nuovo valore.

Sezione WATCH

Cosa accade se si vuole tenere traccia di uno stato di variabile nel tempo o in metodi diversi? Può essere noioso cercare la variabile ogni volta. È qui che la sezione WATCH è utile.

È possibile selezionare il pulsante Aggiungi espressione (visualizzato come segno più: +) per immettere un nome di variabile o un'espressione da controllare. In alternativa, è possibile fare clic con il pulsante destro del mouse su una variabile nella sezione VARIABLES e selezionare Add to watch.

Tutte le espressioni all'interno della sezione WATCH verranno aggiornate automaticamente durante l'esecuzione del codice.

Sezione CALL STACK

Ogni volta che il codice immette un metodo da un altro metodo, viene aggiunto un livello di chiamata allo stack di chiamate dell'applicazione. Quando l'applicazione diventa complessa ed è presente un lungo elenco di metodi chiamati da altri metodi, lo stack di chiamate rappresenta la traccia delle chiamate al metodo.

La sezione CALL STACK è utile quando si tenta di trovare il percorso di origine per un'eccezione o un'espressione WATCH. Se l'applicazione genera un'eccezione imprevista, nella console verrà spesso visualizzato un messaggio simile al seguente:

Exception has occurred: CLR/System.DivideByZeroException
An unhandled exception of type 'System.DivideByZeroException' occurred in Debug1.dll: 'Attempted to divide by zero.'
    at Program.<<Main>$>g__WriteMessage|0_1() in C:\Users\howdc\Desktop\Debug1\Program.cs:line 27
    at Program.<<Main>$>g__Process1|0_0() in C:\Users\howdc\Desktop\Debug1\Program.cs:line 16
    at Program.<Main>$(String[] args) in C:\Users\howdc\Desktop\Debug1\Program.cs:line 10

Il gruppo di righe rientrato sotto il messaggio di at Program ... errore è denominato analisi dello stack. L'analisi dello stack elenca il nome e l'origine di ogni metodo chiamato che ha portato all'eccezione. Le informazioni possono essere un po' difficili da decifrare, perché possono includere anche informazioni dal runtime .NET. In questo esempio, l'analisi dello stack è piuttosto pulita ed è possibile osservare che l'eccezione si è verificata in un metodo denominato WriteMessage. Lo stack ha origine in un metodo denominato Main, che è la sezione delle istruzioni di primo livello dell'applicazione console.

La sezione CALL STACK consente di evitare la difficoltà di decifrare un'analisi dello stack in disordine con informazioni di runtime .NET. Filtra le informazioni indesiderate per mostrare solo i metodi pertinenti dal codice personalizzato per impostazione predefinita. È possibile rimuovere manualmente lo stack di chiamate per scoprire dove ha avuto origine l'eccezione.

Sezione BREAKPOINTS

La sezione BREAKPOINTS visualizza le impostazioni correnti del punto di interruzione e può essere usata per abilitare o disabilitare punti di interruzione specifici durante una sessione di debug.

Configurare l'applicazione e avviare la configurazione

Quando si lavora su un'applicazione console che legge l'input dell'utente, è probabile che sia necessario aggiornare il file di configurazione di avvio.

  1. Aggiornare il codice nel file Program.cs come indicato di seguito:

    string? readResult;
    int startIndex = 0;
    bool goodEntry = false;
    
    int[] numbers = { 1, 2, 3, 4, 5 };
    
    // Display the array to the console.
    Console.Clear();
    Console.Write("\n\rThe 'numbers' array contains: { ");
    foreach (int number in numbers)
    {
        Console.Write($"{number} ");
    }
    
    // To calculate a sum of array elements, 
    //  prompt the user for the starting element number.
    Console.WriteLine($"}}\n\r\n\rTo sum values 'n' through 5, enter a value for 'n':");
    while (goodEntry == false)
    {
        readResult = Console.ReadLine();
        goodEntry = int.TryParse(readResult, out startIndex);
    
        if (startIndex > 5)
        {
            goodEntry = false;
            Console.WriteLine("\n\rEnter an integer value between 1 and 5");
        }
    }
    
    // Display the sum and then pause.
    Console.WriteLine($"\n\rThe sum of numbers {startIndex} through {numbers.Length} is: {SumValues(numbers, startIndex)}");
    
    Console.WriteLine("press Enter to exit");
    readResult = Console.ReadLine();
    
    // This method returns the sum of elements n through 5
    static int SumValues(int[] numbers, int n)
    {
        int sum = 0;
        for (int i = n; i < numbers.Length; i++)
        {
            sum += numbers[i];
        }
        return sum;
    }
    
  2. Prenditi un minuto per esaminare il codice.

    Tenere presente quanto segue:

    • Il codice specifica una matrice integer contenente cinque numeri.
    • Il codice visualizza l'output nella console.
    • Il codice richiede all'utente di immettere un numero n di elemento iniziale usato per sommare gli elementi n della matrice tramite 5.
    • Il codice calcola la somma in un metodo, visualizza i risultati nella console e quindi sospende.

    Annotazioni

    Il pannello DEBUG CONSOLE non supporta l'input dell'utente dalla console.

  3. Nel menu File di Visual Studio Code, selezionare Salva.

  4. Scegliere Rimuovi tutti i punti di interruzione dal menu Esegui.

    In questo modo vengono rimossi tutti i punti di interruzione rimanenti dall'esercizio precedente.

  5. Nella visualizzazione ESEGUI ED ESEGUI DEBUG selezionare Avvia debug.

  6. Si noti che si verifica un errore quando viene eseguita la riga di Console.Clear(); codice.

  7. Sulla barra degli strumenti Debug selezionare Arresta.

  8. Passare alla visualizzazione EXPLORER e quindi aprire il file launch.json nell'editor.

  9. Aggiornare il valore dell'attributo console nel modo seguente:

    "console":"integratedTerminal",
    
  10. Nel menu File di Visual Studio Code selezionare Salva e quindi chiudere il file launch.json.

Esaminare l'output dell'applicazione e identificare i problemi

La revisione dell'output dell'applicazione può rivelare problemi di logica trascurati durante la scrittura del codice.

  1. Tornare alla visualizzazione RUN AND DEBUG.

  2. Nella visualizzazione ESEGUI ED ESEGUI DEBUG selezionare Avvia debug.

    I messaggi visualizzati nel pannello DEBUG CONSOLE mostrano il debugger collegato all'applicazione Debug101.dll .

  3. Si noti che non vengono visualizzati messaggi di errore.

    La modifica del valore dell'attributo console da internalConsole a integratedTerminal nel file di configurazione di avvio ha risolto l'errore della console. Ma ora è necessario individuare la console che contiene l'output.

  4. Nell'area Pannelli sotto l'Editor passare dal pannello DEBUG CONSOLE al pannello TERMINALE.

  5. Si noti che l'esecuzione del codice è stata sospesa al messaggio che richiede all'utente di immettere un valore per n.

    L'output nel pannello TERMINALE dovrebbe essere simile al seguente:

    
    The 'numbers' array contains: { 1 2 3 4 5 }
    
    To sum values 'n' through 5, enter a value for 'n':
    
  6. Al prompt dei comandi TERMINAL immettere 3

  7. Esaminare l'output dell'applicazione.

    L'output nel pannello TERMINALE dovrebbe essere simile al seguente:

    
    The 'numbers' array contains: { 1 2 3 4 5 }
    
    To sum values 'n' through 5, enter a value for 'n':
    3
    
    The sum of numbers 3 through 5 is: 9
    press Enter to exit
    
  8. Prendere in considerazione il valore segnalato di e i valori degli elementi della sum matrice da 3 a 5 visualizzati nella parte superiore della console.

    Il messaggio indica: The sum of numbers 3 through 5 is: 9. Tuttavia, gli elementi della matrice da 3 a 5 sono 3, 4e 5. La somma segnalata non dovrebbe essere 12?

    È possibile usare la sezione VARIABLES della visualizzazione RUN AND DEBUG per analizzare il problema.

Monitorare lo stato della variabile

In alcuni casi, è sufficiente monitorare lo stato della variabile per identificare il problema di logica nell'applicazione.

  1. Impostare un punto di interruzione nella riga di codice seguente:

    Console.WriteLine($"\n\rThe sum of numbers {startIndex} through {numbers.Length} is: {SumValues(numbers, startIndex)}");
    
  2. Nella visualizzazione ESEGUI ED ESEGUI DEBUG selezionare Avvia debug.

  3. Passare dal pannello DEBUG CONSOLE al pannello TERMINALE.

  4. Al prompt dei comandi TERMINAL immettere 3

    L'esecuzione del codice verrà sospesa in corrispondenza del punto di interruzione.

  5. Esaminare la sezione VARIABLES della visualizzazione RUN AND DEBUG.

    Si noti che startIndex è stato assegnato il valore immesso, ovvero 3.

  6. Selezionare Esegui istruzione.

  7. Si noti che le sezioni VARIABLES e CALL STACK vengono aggiornate.

    La sezione CALL STACK mostra che l'esecuzione del codice è stata spostata nel SumValues metodo .

    La sezione VARIABLES, che elenca le variabili locali, mostra il valore dell'intero n. Al parametro n del metodo viene assegnato il relativo valore dall'argomento startIndexdella chiamata al metodo . In questo caso, la modifica ai nomi delle variabili rende chiaro che il valore è stato passato, non un puntatore di riferimento.

    Annotazioni

    In questo caso, è possibile visualizzare la maggior parte del codice nell'editor, pertanto potrebbe non essere necessaria la sezione CALL STACK, ma quando si lavora su applicazioni di grandi dimensioni con chiamate di metodo annidate e interconnesse in modo approfondito, il percorso di esecuzione illustrato nella sezione CALL STACK può essere estremamente utile.

  8. Continuare a selezionare Esegui istruzione fino a quando il valore assegnato a sum non è più 0.

  9. Esaminare le informazioni visualizzate nella sezione VARIABLES.

    Dovrebbe essere visualizzata la seguente schermata:

    Screenshot che mostra la sezione Variabili della visualizzazione Esecuzione e debug.

    Si noti che il valore assegnato a sum è passato da 0 a 4.

  10. Per espandere la numbers matrice, selezionare numeri [int[]].

    Screenshot che mostra gli elementi della matrice espansa nella sezione Variabili della visualizzazione Esegui e debug.

  11. Tenere presente che è possibile accedere agli elementi di matrice usando numeri di indice in base zero.

    In questo caso, l'errore logico è una discrepanza tra le istruzioni nell'interfaccia utente e il codice sottostante. L'interfaccia utente fa riferimento agli elementi della matrice da 1 a 5. Tuttavia, il codice usa il valore immesso dall'utente per accedere agli elementi della matrice in base zero. L'elemento della matrice con un indice di 3 archivia un valore di 4. Il codice non compensa i numeri di indice in base zero.

  12. Per terminare la sessione di debug, selezionare Arresta.

  13. Prendere in considerazione il modo in cui è possibile risolvere il problema.

    Questo problema potrebbe essere corretto nell'interfaccia utente richiedendo all'utente di immettere un valore compreso tra 0 e 4. Può anche essere corretto nel codice sottraendo 1 dal valore immesso. In generale, l'obiettivo dovrebbe essere chiaro e facile da seguire. In questo caso potrebbe essere preferibile aggiornare il codice come indicato di seguito:

    Console.WriteLine($"\n\rThe sum of numbers {startIndex} through {numbers.Length} is: {SumValues(numbers, startIndex - 1)}");
    

    L'esecuzione del codice aggiornato produrrà l'output seguente:

    Screenshot che mostra l'output dopo l'aggiornamento della logica dell'applicazione.

  14. Aggiornare il codice usando l'approccio suggerito e quindi salvare il file Program.cs.

  15. Cancellare il punto di interruzione, rieseguire l'applicazione nel debugger e verificare che il risultato previsto sia visualizzato nel terminale.

    È stato appena usato lo stato della variabile per identificare e risolvere un problema di logica. Ottimo lavoro.

Monitorare le espressioni di controllo

La sezione WATCH può essere usata per monitorare le espressioni basate su una o più variabili.

Si supponga di lavorare su un'applicazione che esegue calcoli numerici su un set di dati. Si ritiene che il codice produa risultati inaffidabili quando il rapporto tra due variabili numeriche è maggiore di 5. È possibile usare la sezione WATCH per monitorare il rapporto calcolato.

  1. Aggiornare il file Program.cs con il codice seguente:

    bool exit = false;
    var rand = new Random();
    int num1 = 5;
    int num2 = 5;
    
    do
    {
        num1 = rand.Next(1, 11);
        num2 = num1 + rand.Next(1, 51);
    
    } while (exit == false);
    
  2. Salvare il file Program.cs.

  3. Impostare un punto di interruzione sulla riga di codice finale.

  4. Impostare l'espressione WATCH seguente:

    num2 / num1 > 5
    
  5. Nella visualizzazione ESEGUI ED ESEGUI DEBUG selezionare Avvia debug.

  6. Si notino i valori visualizzati nelle sezioni VARIABLES e WATCH.

  7. Selezionare Continua finché non viene visualizzata l'espressione WATCH restituisce true.

    Se l'espressione WATCH ha restituito true nella prima iterazione, selezionare Continua alcune volte o fino a quando non viene visualizzata true una seconda volta.

  8. Prendere in considerazione il modo in cui viene usata la sezione WATCH.

    In questo scenario è stato determinato che il codice produce risultati inaffidabili quando il rapporto tra due variabili numeriche è maggiore di 5. È stata creata un'espressione nella sezione WATCH che rappresenta questa condizione. È ora possibile usare la sezione WATCH per tenere traccia di tale condizione.

Modificare il valore assegnato a una variabile nella sezione VARIABLES

In alcuni casi può essere necessario creare manualmente una condizione a livello di codice. La sezione VARIABLES della vista RUN AND DEBUG consente di eseguire questa operazione modificando lo stato di una variabile in fase di esecuzione.

  1. Esaminare il codice in esecuzione.

    Si noti che il codice non esce mai dal do ciclo perché exit non sarà truemai . Questa non è una condizione a livello di codice che è necessario modificare in un'applicazione reale, ma dimostra la funzionalità.

  2. Nella sezione VARIABLES fare clic con il pulsante destro del mouse su exit [bool]e quindi scegliere Imposta valore.

    La sezione VARIABLES consente di modificare il valore assegnato a una variabile in fase di esecuzione. Ciò può essere utile quando si vuole vedere in che modo il codice reagisce a una determinata condizione.

  3. Per impostare il valore di exit su true, digitare true e quindi premere INVIO.

    In questo caso, la modifica del valore di exit in true causerà la chiusura dell'applicazione quando viene eseguita l'istruzione while .

  4. Seleziona Continua.

  5. Si noti che nel pannello DEBUG CONSOLE viene visualizzato un messaggio che informa che il programma è stato chiuso.

Congratulazioni! Le sezioni VARIABLES e WATCH della visualizzazione RUN AND DEBUG sono state usate correttamente.

Riepilogo

Ecco i concetti più importanti di questa unità da ricordare:

  • Monitorare lo stato della variabile usando la sezione VARIABLES della visualizzazione RUN AND DEBUG.
  • Tenere traccia di un'espressione nel tempo o in metodi diversi usando la sezione WATCH della visualizzazione RUN AND DEBUG.
  • Usare la sezione CALL STACK della vista RUN AND DEBUG per trovare il percorso di origine di un'eccezione o un'espressione WATCH.
  • Usare la sezione VARIABLES per modificare il valore assegnato di una variabile in fase di esecuzione.