Post

C# - The VS Code Debugger Interface

Run menu options

The Visual Studio Code Run menu provides easy access to some common run and debug commands.

VS Code Run Menu Options VS Code Run Menu Options

The Run menu provides menu options that are grouped into six sections.

  1. Start and stop applications. This section of the menu includes options for starting and stopping code execution, with and without the debugger attached.
  2. Launch configurations. This section of the menu provides access to examine or create launch configurations.
  3. Runtime control. This section of the menu enables the developer to control how they want to advance through the code. Controls are enabled when execution has paused during a debug session.
  4. Set Breakpoints. This section of the menu enables the developer to set breakpoints on code lines. Code execution pauses on Breakpoints during a debug session.
  5. Manage Breakpoints. This section of the menu enables the developer to manage breakpoints in bulk rather than individually.
  6. Install Debuggers. This section of the menu opens the Visual Studio Code EXTENSIONS view filtered for code debuggers.

Run and Debug view user interface

The RUN AND DEBUG view provides access to runtime tools that can be invaluable during the debug process.

VS Code Run and Debug Menu Options VS Code Run and Debug Menu Options

  1. Run and Debug controls panel. Used to configure and start a debug session.
  2. VARIABLES section. Used to view and manage variable state during a debug session.
  3. WATCH section. Used to monitor variables or expressions. For example, you could configure an expression using one or more variables and watch it to see when a particular condition is met.
  4. CALL STACK section. Used to keep track of the current point of execution within the running application, starting with the initial point of entry into the application. The call stack shows which method is currently being executed, as well as the method or methods in the execution path that led to the current point of execution (current line of code).
  5. BREAKPOINTS section. Displays the current breakpoint settings.
  6. Debug toolbar. Used to control code execution during the debug process. This toolbar is only displayed while the application is running.
  7. Current execution step. Used to identify the current execution step by highlighting it in the Editor. In this case, the current execution step is a breakpoint (breakpoints are marked with a red dot to the left of the line number).
  8. DEBUG CONSOLE. Used to display messages from the debugger. The DEBUG CONSOLE panel is the default console for console applications and is able to display output from Console.WriteLine() and related Console output methods.

Controls panel for the Run and Debug view

At the top of the RUN AND DEBUG view, you can find the launch controls:

VS Code Run and Debug Controls Panel VS Code Run and Debug Controls Panel

  1. Start debugging. This button (a green arrow) is used to start a debug session.
  2. Launch configurations. This dropdown menu provides access to launch configurations. The selected option is displayed.
  3. Open ‘launch.json’. This button (a gear shape) can be used to open the launch.json file, where you can edit the launch configuration if needed.
  4. Views and More Actions. This button (an ellipsis) enables you to show/hide sections of the debug panel as well as the DEBUG CONSOLE panel.

Debug toolbar

The Debug toolbar provides execution controls while your application is running.

VS Code Debug toolbar VS Code Debug toolbar

  1. Pause/Continue. This button can be used to pause execution when the code is running and Continue when code execution has been paused.
  2. Step Over. This button can be used to execute the next method as a single command without inspecting or following its component steps.
  3. Step Into. This button can be used to enter the next method or code line and observe line-by-line execution steps.
  4. Step Out. When inside a method, this button can be used to return to the earlier execution context by completing all remaining lines of the current method as though they were a single command.
  5. Restart. This button can be used to terminate the current program execution and start debugging again using the current configuration.
  6. Stop. This button can be used to terminate the current program execution.

In addition to six execution controls, the Debug toolbar provides a “handle” on the left side that enables the developer to reposition the toolbar, and a “More” dropdown on the right side that enables the developer to disconnect the debugger.

VARIABLES section

  • The VARIABLES section organizes your variables by scope. The Locals scope displays the variables in the current scope (the current method).
  • The top-level statements section of a console application is considered its own method. A method named Main.
  • You can unfold (expand) the displayed scopes by selecting the arrow to the left of the scope name. You can also unfold variables and objects. The following screenshot shows the numbers array unfolded under the Locals scope.
  • It’s also possible to change the value of a variable at runtime using the VARIABLES section. You can double-click the variable name and then enter a new value.

VS Code VARIABLES section VS Code VARIABLES section

WATCH section

  • What if you want to track a variable state across time or different methods? It can be tedious to search for the variable every time. That’s where the WATCH section comes in handy.
  • You can select the Add Expression button (appears as a plus sign: +) to enter a variable name or an expression to watch. As an alternative, you can right-click a variable in the VARIABLES section and select Add to watch.
  • All expressions inside the WATCH section will be updated automatically as your code runs.

CALL STACK section

  • Every time your code enters a method from another method, a call layer is added to the application’s call stack. When your application becomes complex and you have a long list of methods called by other methods, the call stack represents the trail of method calls.

  • The CALL STACK section is useful when you’re trying to find the source location for an exception or WATCH expression. If your application throws an unexpected exception, you’ll often see a message in the console that resembles the following:

1
2
3
4
5
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
  • The indented group of at Program … lines under the error message is called a stack trace.
  • The stack trace lists the name and origin of every method that was called leading up to the exception.
  • The information can be a bit difficult to decipher though, because it can also include information from the .NET runtime.
  • In this example, the stack trace is pretty clean and you can see that exception occurred in a method named WriteMessage.
  • The stack originates in a method named Main, which is the top-level statements section of the console application.
  • The CALL STACK section can help you to avoid the difficulty of deciphering a stack trace that’s cluttered with .NET runtime information.
  • It filters out unwanted information to show you only the relevant methods from your own code by default.
  • You can manually unwind the call stack to find out where the exception originated.

Example of using the WATCH Section and modifying the value assigned to a variable in the VARIABLES section

Monitor watch expressions

  • The WATCH section can be used to monitor expressions that are based on one or more variables.
  • Suppose you’re working on an application that performs numeric calculations on a data set.
  • You believe that your code produces unreliable results when the ratio between two numeric variables is greater than 5.
  • You can use the WATCH section to monitor the calculated ratio.
  • Here is an example code to test this scenario:
1
2
3
4
5
6
7
8
9
10
11
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);
  • Set a breakpoint on the final code line.
  • Set the following WATCH expression (using the plus sign in the WATCH section):
1
num2 / num1 > 5
  • On the RUN AND DEBUG view, select Start Debugging.
  • Notice the values displayed in the VARIABLES and WATCH sections.
  • Select Continue until you see the WATCH expression evaluate to true.
  • If the WATCH expression evaluated to true on the first iteration, select Continue a few more times or until you see true a second time.
  • Take a minute to consider how the WATCH section is being used.
    • In this scenario, you determined that your code produces unreliable results when the ratio between two numeric variables is greater than 5.
    • You constructed an expression in the WATCH section that represents this condition.
    • You can now use the WATCH section to track that condition.

Modify the value assigned to a variable in the VARIABLES section

  • There may be times when you want to create a programmatic condition manually.
  • The VARIABLES section of the RUN AND DEBUG view enables you to do this by changing the state of a variable at runtime.
  • The currently running application will never exit out of the do loop because exit will never be true.
  • This isn’t a programmatic condition that you’ld need to alter in a real-world application, but it demonstrates the capability.
  • In the VARIABLES section, right-click exit [bool], and then select Set Value.
    • The VARIABLES section enables you to change the value assigned to a variable at runtime.
    • This can be useful when you want to see how your code reacts to a particular condition.
  • To set the value of exit to true, type true and then press Enter.
    • In this case, changing the value of exit to true will cause the application to close when the while statement is executed.
  • Select Continue.
  • Notice that the DEBUG CONSOLE panel displays a message informing you that the program has exited.
This post is licensed under CC BY 4.0 by the author.