Sometimes your application is not functioning the way you intended. It’s not throwing any exceptions, either the data it’s producing is incorrect, or it is executing code it shouldn’t. To troubleshoot the issue so you can find and fix the problem will take debugging knowledge and skill.
At the heart of the debugging process are “breakpoints.” A breakpoint is a point in your code where you want the execution of your application to pause. During this “break” in execution, you can inspect the value of your variables as well as watch the control flow of the application occur. Adding a breakpoint to a line of code lets you determine precisely where the execution will pause.
Before discussing how to set breakpoints in your code, I’m going to share some thoughts one “where” you should place the breakpoints.
The critical thing to remember is that when you set a breakpoint in Visual Studio, the execution pauses right BEFORE that code statement executes. This fact means when the application pauses, the line of code on with a breakpoint has not yet executed. With this in mind, it makes sense that you would put a breakpoint on the code statement where you want to start debugging.
Placing a breakpoint too early in the execution will result in extra debugging overhead. It is also essential to ensure the code statement with a breakpoint is part of the application flow. If that line of code never gets hit, the code will never pause.
There are a few ways to add a breakpoint to a code statement. With the desired line of code selected, you can do any of the following:
· Right-click on the code and select “Breakpoint -> Insert Breakpoint”
· Open the Debug menu and select “Toggle Breakpoint.”
· Click in the far left margin of the IDE.
When you set a breakpoint, a red circle appears in the margin, and Visual Studio highlights the line of code on which it has placed a breakpoint
When you run the application, execution will halt right before it hits that line of code. When that occurs, Visual Studio will highlight the code statement, and an arrow will show up on the red circle.
This highlight is Visual Studio’s way of telling you that this line will be the next one it executes.
A tracepoint will allow you to write a message Output window when the specified code statement is reached. When writing the message, write it as you would when using string interpolation. Tracepoint messages allow you to use curly braces to utilize variable names and expressions in your message.
With a tracepoint, you have the option of whether or not the application will continue execution after the message is written. If you uncheck “Continue code execute,” the application will pause execution at that line, similar to a breakpoint.
As you can see in the following screenshot, the code has paused on my tracepoint, and the Output window has the information I wanted to display.
You will find that sometimes your application works perfectly fine 90% of the time, but once a particular value is entered into the system, something unexpected happens. Just placing a normal breakpoint into your system and trying to troubleshoot from there can be time-consuming.
Luckily, you have the option to set a condition on the breakpoint, and the code will only halt execution when that condition is true. Loops are a principal place to use condition breakpoints since you only what to start debugging when questionable data is about to be processed.
To set a condition breakpoint, set a normal breakpoint utilizing your preferred method. Once the breakpoint is created, right-click on the red circle and select “Conditions.” Doing this will open a subform that allows you to set the condition. In the following screenshot, I want my application to halt execute when the FOR loop is processing the name “Kristy.”
Notice the PLUS symbol on the red circle. This symbol lets you know that the breakpoint has a condition. To troubleshoot my issue, I may want to see all the names that were processed before Kristy, but I don’t want to pause on every loop iteration. To do this, I’m going to create a tracepoint. This time I will allow the code to continue execution when I create the tracepoint.
Notice that when a tracepoint is not halting the execution, a red rhombus replaces the red circle in the margin.
When I run the application, the execution halts when it reaches “Kristy,” and the Output window tells me all the names already processed.
There are a few windows in Visual Studio that will help you troubleshoot your issues. If any of these windows are not currently visible in Visual Studio, open the Debug menu and hover over “Window” as from there you will be able to open these windows in your IDE. It is important to remember that the information in these windows will only show up if the application execution is paused.
The Locals window is beneficial when debugging since it shows you the name, value, and data type of every variable that is being used at the point you halted the execution of your application.
As I step through the halted code, which you learn about later, the Locals window will update the variable information. This functionality provides a real-time view of the data being used by your application.
If you just wanted to keep an eye on just one or two variables and didn’t want to track them in the Locals window, you can use the Watch window. The watch window allows you to examine the variable and properties you choose as they are updated and utilized.
To add a variable to the Watch window, you can right-click on the variable and select “AddWatch.” You can also type the variable name into the Watch window, and it will be added.
The Immediate window is used during debugging to execute code against the current state of the application. You can print out expression results, view variable values, or test changes to the current codebase. The immediate window works similarly to the Windows command window. You type in commands, press Enter, then view the results.
You can use the Immediate window to change the current value of variables. This practice is usually done to test how a process would change with a different value.
To display information in the Immediate window, you can use the Debug.Print command or use the shortcut key, the question mark.
Advancing the Code
Setting a breakpoint on a line of code will pause the execution of the application immediately before the line executes. Once the application halts, you can use everything you learned so far to see the current state of the application. If there is nothing further you want to see or investigate, you can continue the application by pressing F5 or clicking the “Continue” button.
However, on most occasions, you will want to advance the code one step at a time so you can see what the application is doing so you can debug the issue causing you problems.
Once your application is paused, you can advance the execution of the program line by line by using the Step Into command.
You can use the Step Into command in several ways.
· Press F11
· Debug -> Step Into
· Step Into button (blue arrow point to a dot)
Remember, when a statement is highlighted, this means it will be the next statement to be executed. Many new coders forget this an wonder why the coding isn’t working when it’s highlighted.
Step Into will traverse every line in the application flow. Meaning any method being called will be executed line by line with the Step Into command. In the following GIF, you will see the execution of the code step into the GreetUser method as the F11 key is pressed.
While it may be beneficial to step into methods when you aren’t sure where a problem is occurring, there will be times where you know for sure the problem isn’t happening in the method being called. Instead of stepping into the method and navigating its code line by line, you have the option to step over the method.
You can use the Step Into command in several ways.
· Press F10
· Debug -> Step Over
· Step Into button (blue arrow jumping over a dot)
It’s important to understand that the code in the method is being executed when you step over it. It’s just being executed as a code block instead of individual statements, allowing you to focus on the code that may be causing your issue.
As you can see in this GIF, I was able to step over the method, but the code that greets the user still executed.
The Step Out command is a shortcut to get out of a method that you stepped into while debugging. There may be times when you only want to execute the beginning of a method line by line then want to run the rest of the code as a block. There will also be times while debugging where you accidentally step into a method.
To run the code from the highlighted pause point to the end of the method, use the Step Out command. You can use the Step Into command in several ways.
· Press Shift + F11
· Debug -> Step Out
· Step Into button (blue arrow pointing away from a dot)
In this GIF, I use the Step Out command before the “Hello” line executes. The remaining code in the method executes as a block. The debugging control returns to the Main method after the method call.