Microsoft & .NETVisual C#Visual C++ 2005 IDE Enhancements, Part 5: Variable Display

Visual C++ 2005 IDE Enhancements, Part 5: Variable Display

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Inspecting the state of a variable during a debug session is a fundamental activity of producing software. For simple data types such as integers and short strings, the textbox-based display of a variable’s value is adequate. In fact, it’s been used in debuggers for many years. However, for complex data types that have many internal variables and that have deep and complex relations with other types, the traditional display offered by debug windows like Quick Watch is far from ideal.

Visual C++ 2005 offers a number of improvements in the way data can be examined during a debug session. The first improvement is the DataTip. A DataTip is similar to the QuickWatch window in terms of its functionality, but rather than using a modal window that needs to be manually activated, a DataTip will pop up in the same manner as a ToolTip. To access the DataTip for a variable, simply hover over any line of code where the variable is used when the debugger is in Break mode. A ToolTip-like window will appear, displaying the same top-level debug information that the Watch window would display. As with the Watch window, expansion is possible so that you can examine the data member of a variable. Figure 1 shows an expanded DataTip for a SqlConnection object.

Figure 1. DataTips in Visual Studio.NET 2005

Controlling Variable Display

Looking at the amount of data displayed in Figure 1, it is apparent that although DataTips make it very easy to bring up information about the state of a variable, navigating through the great quantity of information that a complex variable such as a database connection possesses is still time consuming and difficult. To allow the member variables of a type to be organized so that the most relevant items are the most visible to a user, the Visual C++ debugger ships with the ability to customize the display of classes in debug windows. This ability has been present in Visual C++ for many versions, and many developers will be familiar with the use of autoexp.dat and mcee_mc.dat for controlling the display of native and managed types, respectively.

Both these files have expanded considerably going from Visual C++ 2003 to 2005. The file size of autoexp.dat has gone from 6 Kb to 51 Kb and the file size of mcee_mc.dat has gone from 4 Kb to 11 Kb (these figures are based on Beta 2 of Visual C++ 2005). The increase in size represents both an increase in the coverage of the types as well as enhanced syntax that makes the display of types much richer. In mcee_mc.dat, the improved functionality revolves primarily around the display of collections. Settings for the collections that ship with the .NET Framework Library, as well as the STL, are included with this file. For a .NET ArrayList and HashTable, the syntax for the display is as follows:

System.Collections.ArrayList{
   children(
      #array(
         expr :   ($c._items)[$i],
         size :    $c._size
         ))
}

System.Collections.Hashtable.bucket{
   children(
      #if($e.hash_coll == 0)
      (
         #(
            [empty bucket]:
         )
      )
      #else
      (
         #(
            key: $e.key ,
            val: $e.val
         )
      )
   )
}

System.Collections.Hashtable{
   children(#(buckets: $c.buckets))
}

Figure 2 shows the result of these settings.

Figure 2. ArrayList and Hashtable Variables in the Watch Window

Although the use of these macro-like expressions is not documented, the number of special constants such as #array is fairly limited, and custom settings can be constructed based on existing settings without too much pain. Once Visual C++ 2005 has been released and any bugs relating to using this syntax in custom types have been ironed out, I’ll revisit this topic and show how to use these collection visualizers for your own types.

The syntax for autoexp.dat (which is used to control the display of unmanaged types) is similar, but the complexity of unmanaged types and the use of features like unions and nested templates mean that the types described tend to be more complex. As with mcee_mc.dat, the syntax for describing types is currently undocumented, but there is a wealth of examples that span types from the Windows SDK, STL, ATL, and MFC. For most developers who have used STL with Visual C++, trying to figure out the values that a collection holds is very painful. The massively expanded autoexp.dat addresses this problem quite well. Figure 3 shows the debug display of an STL vector in Visual C++ 2003 that contains three elements: 0, 1, and 2. Determining this from the debug display is not possible.

Figure 3. STL Vector Display in Visual C++ 2003

Figure 4 shows the display of the same variable in Visual C++ 2005. The difference in usefulness between the two displays is obvious.

Figure 4. The Same Variable in Visual C++ 2005

Data Visualizers

At some stage, despite all the attempts at clever display techniques, textboxes just don’t cut it for displaying large and complex variables. Most developers have had to add a DataGrid to a dummy form so they can debug the contents of a DataSet or copy the data from an XML string into a file so they can view it with the auto-indenting and node-collapsing abilities of Internet Explorer. As variables get more complex, the need for customized displays such as a DataGrid or a specialized XML viewer increases. In recognition of this need, Visual Studio ships with a new technology called Debug Visualizers. A Debug Visualizer is simply a custom display form that is associated with a particular type and accessible from any of the standard debug windows like Autos and Locals.

Before going into the process of writing a Visualizer, take a look at one in action. Figure 5 shows the Autos window with a System::String variable included. Notice the small magnifying glass icon at the end of the variable’s value.

Figure 5. Type with a Visualizer Available

Clicking on the magnifying glass brings up the Visualizer associated with the type (as shown in Figure 6). In this case, the display is of a simple string that was not difficult to inspect with the standard textbox-based debug display, but as the string becomes larger, the usefulness of the string Visualizer increases. Planned for inclusion in the final release (but not working in Beta 2) are Visualizers for DataSets, XML, and HTML.

Figure 6. String Debug Visualizer Display

Writing a Visualizer is a reasonably simple task. Rather than forcing the developer to tread a painful line between the native core of the IDE and the managed code responsible for large sections of the UI, writing Visualizers is purely a managed code exercise. Visual Studio ships with a walkthrough that goes through each step in detail, but the basic tasks involve implementing the IVisualizerObjectProvider interface for the type, which will live inside Visual Studio and display the Visualizer UI, and deriving from VisualizerObjectSource for the type that will live inside the process that is being debugged. The Visualizer user interface is implemented through an IDialogVisualizerService-implementing object, which will display Windows Forms controls. To hook all the types together, the DebuggerVisualizerAttribute is used. An optional feature of a debug visualizer is the ability to modify data in the variable being displayed, and it can do this by changing values in the object or by creating a replacement object.

Deployment of a debug visualizer is a simple story, with no Registry settings required. The assembly containing the visualizer is simply placed in a known directory (either [Visual Studio Install Path]Microsoft Visual Studio 8Common7PackagesDebuggerVisualisers or My DocumentsVisual StudioVisualizers), and Visual Studio uses reflection to pick up the assembly and load the correct types.

About the Author

Nick Wienholt is an independent Windows and .NET consultant based in Sydney, Australia. He is the author of Maximizing .NET Performance from Apress, and specializes in system-level software architecture and development with a particular focus on performance, security, interoperability, and debugging. Nick can be reached at NickW@dotnetperformance.com.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories