I love all things diagnostics. After installing VS 2010 Beta 2, the first thing I had to look at my favorite tool of all, the debugger. All the familiar features are there that we've been using for ages, such as advanced breakpoints and the killer expression evaluator, but the team has obviously spent a lot of effort to polish the debugging experience, especially when it comes to the user interface.
What's extra special is all of the features in the debugger I'll discuss here, unless otherwise noted, apply to both .NET and native C++ development. For this article my focus is on the key things I find interesting and are new or different from Beta 1. See the Visual Studio 2010 Beta 2 documentation for the complete list. In addition, some features, such as the newly renamed IntelliTrace (previously known as Historical Debugging) are so big and sexy they deserve their own articles. As always, please ask questions in the comments or email me.
The first thing I had to do before diving into the debugger was set a few debugger options. I feel the defaults debugger settings aren't the best for the type of development and debugging I do. Instead of having to go to the Tools, Options menu to get to the options, the Debug menu now can jump you right to the most important settings in the entire IDE, the debugger settings of course.
In the General page, I uncheck "Enable Just My Code (Managed Only)" because I need to debug everything, even things that don't have code and believe debug optimized builds is just a wee bit important. I also check "Enable .NET Framework source stepping" because I loves me some framework code magic. In the Edit and Continue page I Disable all Edit and Continue as I just don't use it. Not to start the wars again, but here's why. In the Native page, I check Enable Load DLL exports so my native debugging shows me the exported function names, which I have never understood why this option is not on by default. My next stop is the Symbols page and I was surprised that it looked different from Visual Studio 2008.
Instead of making you remember obtuse web site names for downloading public symbols from Microsoft, you just have to check the "Microsoft Symbol Servers" check box. To verify what symbol servers Visual Studio 2010 will use, I looked in the registry under HKCU\Software\Microsoft\VisualStudio\10.0\Debugger, which houses all your debugger settings. No big shock, but checking the option in the dialog sets the SymbolPath value to "c:\Symbols\MicrosoftPublicSymbols*http://referencesource.microsoft.com/symbols;c:\Symbols\MicrosoftPublicSymbols*http://msdl.microsoft.com/download/symbols." Both of those web sites should be familiar to all Windows developers.
What made me shout out a big "Yes!" is the option to specify excluded modules! If you're using third party components that don't have PDB files, you can drop those DLL and EXE files into the Specify excluded modules and you'll never wait on the debugger trying to look for those missing symbols again. I'd written before on how to set this up manually, but having a UI on the excluded symbols makes life oh so much easier.
Once I started debugging, I noticed an excellent new feature in the debugger that will save you countless hours. If the symbol file you're trying to download from a public symbol server does not exist, the debugger no longer continues to attempt the download every time you debug. If a symbol file from a public symbol server cannot be found, the debugger creates a directory <Cache directory>\MicosoftPublicSymbols\FailedLoads. In that directory, it writes a text file whose name corresponds to filename and GUID identifier for the PDB file. The debugger puts the error message from the public symbol server in the file. On your next debugging session, the debugger looks at the FailedLoads directory and skips the PDB load attempts that failed before. I was shocked at how much faster my debugging startup was because the debugger avoids the network access. I love those small features that you don't initially notice that have a huge impact on your life.
While the .NET 4.0 PDB files and .NET Reference Source are not available just yet, I wanted to see if there were any improvements to .NET Reference Source stepping so I created a new project that targeted .NET 3.5. In my haste to see the new debugger, I had forgotten to uncheck one option in the General page, "Require source files to match exactly match the original." If this switch is set, the debugger can't load the .NET Reference Source because the file checksums don't match as Microsoft adds a copyright to the .NET Reference Source files after the build. Visual Studio 2008 requires turning off the source matching as well. By accidentally leaving the exact file option on, I saw something wonderful. When the debugger couldn't load the .NET Reference Source file it had downloaded, because it didn't match, I saw the usual file open dialog asking me find the.NET Reference Source file manually. I clicked Cancel and got a great new window.
While we've had symbol loading diagnostics for a while, having the same assistance where the debugger is looking for source files is fantastic. This is especially important for those of us who have wondered why a source file couldn't be found when we thought we set up the source paths, this new display will help.
To tell the debugger where you want it to look for your source files, right click on the solution node in the Solution Explorer and choose Properties. In the Common Properties node, select Debug Source Files and add the directories in the Directories list box. These same steps have been in Visual Studio since back in the dark ages of Visual Studio 2002.
The debugger team has been busy giving the Threads window, not to be confused with the Parallel Stacks window, a nice makeover. My favorite option is that now you can search for text that appears in any method on the thread stack. In the following screen shot of a multithreaded application, I wanted to narrow down the threads that had anything with "parallel" in the name.
The searching will automatically hide any threads that don't and use a light yellow highlight to show all those that do. When you're dealing with a bunch of threads being able to narrow down the interesting threads quickly helps. While the Visual Studio 2008 SP1 Threads window shows a popup tool tip showing the stack for the thread, with Visual Studio 2010, as I've shown above, you can expand the stacks inline to make comparison and inspection easier. We've needed this feature for years in the Threads window and you'll be using it constantly.
In Beta 1, we got a glimpse of the future of data tips with the "sticky notes" look. The debugger team finalized the UI so when a data tip is visible, you'll see a pin icon on the end of the data tip. Click it, the data tip will pin to the line and show up every time you debug.
In the following screen shot, I pinned a few data tips to the source lines, hence the pin icons in the gutter along the left side.
In the top pinned data tip, I right clicked on the item and selected "Add Expression" which allowed me to add the Thread.CurrentThread.Name. In the bottom expression, I hovered over the pinned expression until it popped up a grey glyph show below popped up.
Clicking on the down chevron will show the comment box where you enter your comment. You'll be using these comments on the pinned expressions a lot because you'll be adding these all over the place while debugging because it's just so convenient to see the values as you're debugging right in the source code.
Data tips don't just have to be pinned to a source line. If you hover over the data tip and in the grey popup click the middle pin icon, the data tip becomes a floating data tip that will stay positioned to the screen instead of the source line like the following.
These floating data tips let keep an eye on values up the stack or statics/global variables elsewhere in the program. In the little bit of poking I've done, it doesn't look like the automation model allows creating pinned or floating data tips. I'd love a macro that would look at the current function and populate it with all the data tips automatically.
Back in Beta 1, the debugger team had shown us that you can now import and export breakpoints. The good news is that you can do the same with data tips. The Debug menu contains all the data tip and breakpoint import and export commands.
There is a bug in Beta 2 where the data tips don't show up if you have zoomed the editor text to a value other than 100%. That bug kept tripping me up as I find zooming in and out of the text is very convenient while debugging. I'm sure this problem will be fixed in the RTM.
One feature Microsoft has already shown in Beta 1 was the managed minidump debugging support, which we sorely needed. While it's fun for the first fifteen nanoseconds to grind through a minidump with WinDBG and SOS, it gets extremely painful very quickly. With Beta 2, the diagnostic teams finalized managed minidump support and it's something to behold.
The first new part of the managed minidump support is that any time you are debugging a managed application, there's a new menu item on the Debug menu, Save Dump As. Now you can save minidumps of your debugging session as you go along. While that's been there for native code for years, it's great to have it for managed debugging. I'm in the practice of saving minidumps of the process as I'm looking for a hard problem because you may only get it duplicated once. Those minidumps you saved might turn out to be the only states you get to look at leading up to the problem.
Opening minidumps has changed with Visual Studio 2010. Instead of opening the minidump through the File menu, Open Project/Solution, you now open minidumps with File, Open File. Once the file is open, you'll get a nice summary window showing you the architecture, exception information, OS and CLR versions, and the list of loaded modules. On the right side you'll decide the action you want to take which are debugging native only, or debugging mixed (which includes x64 as Microsoft has previously announced).
If you have a minidump with full heap, which contains everything in the address space, after clicking on Debug with Mixed, the minidump loads in the debugger and takes you back in time to when you created the minidump. What I find fascinating about the new minidump support is how seamless it all is. When doing live debugging, you're using the debugger's expression evaluator and the CLR Debugging API to display your objects. None of that exists when you're looking at a minidump. The magic is through an IL interpreter that Mike Stall and others wrote to simulate execution. I encourage you to go read Mike's blog entry about the IL interpreter so you can see how it works.
I created a minidump when I stopped the debugger in the function I used to show the pinned data tips above. After loading the minidump, here's the Autos window at that point. The "i" glyphs in the Value column indicate the IL interpreter did the work to evaluate the expression.
The more I use the Visual Studio 2010 Beta 2 debugger, the more I'm loving it. While you are probably required to use Visual Studio 2008 for builds, you can start using the Visual Studio 2010 Beta 2 debugger today. For native that's always been the case, but it's new for .NET. The magic is that Visual Studio 2010 can target .NET 2.0 so it fully supports builds from Visual Studio 2008 as they both are using the .NET 2.0 compilers. If you're working on WPF, Windows Forms, or console applications, in Visual Studio 2010 Beta 2, go to File, Open Project/Solution and open the .EXE as the solution. Set your breakpoints and you're on your way. For those of you doing ASP.NET or SilverLight, start your web browser and connect to Web.Dev or your site running under IIS. To debug your application, use the Debug, Attach to Process menu to attach and debug to your heart's content.
If you do start using the Visual Studio 2010 Beta 2 debugger, please blog about your experiences. The debugger team would love the feedback. Of course, if you find a bug let them know as well. Now go forth and debug better!