10 Powerful Debugging Tricks with Visual Studio
This article describes 10 most time-saving features of Visual Studio debugger that can be used for debugging any application with Visual Studio.
1. Hover mouse to evaluate expression
Debugging can be challenging. Stepping through a function to understand what went wrong, looking through the call stack to see where did that value come from... In either case adding watch expressions or looking through a list of locals can take quite a time. However, things get easier if you just point your mouse at a variable of interest. Moreover, classes and structures will be expanded with one click, allowing to find the field you need quickly and conveniently.
2. Change values on-the-fly
Debugger is much more than a tool for analyzing crashes and wierd behavior. Many bugs can be prevented by stepping through a freshly written function and checking that it behaves as expected. Sometimes you are curious "would the function behave correctly if this condition was true?". And in most cases it does not mean changing the code and restarting. Just hover the mouse over a variable, double-click at the value and type in the new one!
3. Set next statement
One typical debugging scenario is analyzing why does a function call fail by going through the function step-by-step. And what do you do when you've just discovered that a function called another function that returned an error? Restart debugging? There's a better idea: just drag the yellow statement marker to the line you want to be executed next, like the function that has just failed, and then simply step in. Simple, isn't it?
4. A convenient watch window
Probably, every modern debugger has a watch window. However, what's really cool about the Visual Studio one is how easy you can add and remove variables there. Just click at the empty line, type your expression and press Enter. Or simply press delete button to remove an expression that is no longer needed.
5. Annotated disassembly
Optimizing the performance of the critical parts of your program can be much easier using the interactive disassembly mode. Visual Studio shows you the instructions corresponding to every line of your code and allows running the code step-by-step, as well as setting breakpoints at arbitrary locations. And, of course, the expression evaluation and modification will work just like for the C++ code.
6. Threads window with stacks
Debugging multi-threaded applications can be painful. Or it can be fun. Depends on your debugger. One really nice feature of Visual Studio 2010 is the stack view in the threads window. You can get a convenient overview of all your threads and navigate through their call stacks directly from the window. The screenshot above shows 2 threads of a MacOS application. One of the threads is waiting for an event.
7. Setting breakpoints on-the-fly
Another minor but nontheless timesaving feature of Visual Studio is the ability to set and remove breakpoints while the program is running. VisualGDB supports it by seamlessly stopping the debugged program when you insert or remove a breakpoint and resuming it immediately after. Furthermore, the Enterprise edition allows customizing the method that VisualGDB should use to stop the target (e.g. sending an interrupt command or running a custom script).
8. Memory window
Some bugs are caused by incorrect structure definitions, missing alignment attributes, etc. Seeing the raw memory contents simplifies locating and fixing those bugs. Visual Studio features a convenient memory window that can interpret the values as 8/16/32/64-bit numbers, as well as floating-point numbers and allows changing them on-the-fly by simply typing the new values over the old ones like in a text editor.
9. Conditional breakpoints
If you're trying to reproduce a rare event and getting too many false positives with your breakpoints, you can easily make them conditional! Simply specify the condition for a breakpoint and Visual Studio will automatically ignore the breakpoint when the condition does not hold. The screenshot illustrates how VisualGDB queries the expression value and immediately resumes the execution when the condition is false.
10. Go To Definition
One last feature to mention is not directly related to debugging, rather to exploring big projects. If the IntelliSense paths are set correctly (VisualGDB does it automatically for GCC-based toolchains), you can easily find the definition of a type, variable, function or a preprocessor macro by right-clicking at it and selecting "go to definition".