Improving Visual C++ Debugging with Better Data Display

The ability to customize the summary information for a type in the Watch and Variable windows in the Visual C++ debugger has existed for a long time, and for this reason, the feature doesn’t receive a lot of coverage in new articles and books on the Visual C++ debugger. Even though the display information customization feature is old, it is still incredibly useful for boosting developer productivity, and it is worth reminding more experienced developers that the feature still exists and demonstrating to more recent converts to Visual C++ how it can be used.

The key to customizing type display in the Visual C++ debugger is the autoexp.dat file. This file, which is located in the <install_path>\Common7\Packages\Debugger folder in a Visual Studio 2008 installation, uses a custom syntax to instruct the debugger how to display the summarized information for a particular type. At its simplest form, the syntax is type=[text]<member[,format]>… For a simple type, such as the MFC CPoint class, the autoexp.dat display specification is CPoint =x=<x> y=<y>, which translates to the display shown in Figure 1.

Figure 1: Simple Type Information Display: CPoint

Without the autoexp.dat entry, CPoint will display as shown in Figure 2, which is obviously a lot less useful from a debugging perspective.

Figure 2: CPoint Debug Display without autoexp.dat

The debugger will use the display information for a base type when a derived type has no custom display information of its own. For the case where a type has multiple base types that have custom display information, the first type in the inheritance list that has custom debug information will be used. In this case, defining the debug display for the derived type by combining the autoexp.dat entries for the base types will be the best course of action.

C++ Debug Visualizers

Prior to the release of Visual Studio 2005, autoexp.dat was fairly static from release to release. Visual Studio 2005 saw the release of debug visualizers in the managed world; they allowed for the display of type information in a custom dialog box, and although the increase in debug display in Visual C++ was not as dramatic, the debug display engine in Visual C++ did receive a significant upgrade, and there was a huge increase in autoexp.dat type coverage. The RTM version of Visual C++ 2003 had a 6KB autoexp.dat, whereas the same file for RTM Visual C++ 2005 was 53KB.

One of the areas that received the most focused coverage increase was the STL. Prior to Visual C++ 2005, inspecting the contents of a STL container often required the use of raw pointers and the memory window to trace through the in-memory layout of the collection manually. Less tedious but no less frustrating was the experience of stopping the debugger, adding code to spit out the contents of the collection to the console, and re-running the application.

Figure 3 shows the before- and after-Visual Studio 2005 display of a STL vector containing three elements in the debugger.

Figure 3: STL Vector Display in the Debugger

Looking at the display in Figure 3, it is apparent that there are two display customizations taking place: the summary information for vector is being customized to display the vector length followed by the vector contents; the member variable display is being customized to display each vector element rather than the raw pointers to _Myfirst and _Mylast. The autoexp.dat display for vector is shown below, and the two separate specifications for preview display and children display can be seen.

std::vector<*>{
   children
   (
      #array
      (
         expr :  ($e._Myfirst)[$i],
         size :  $e._Mylast-$e._Myfirst
      )
   )
   preview
   (
      #(
         "[", $e._Mylast - $e._Myfirst , "](",
         #array
         (
            expr : ($e._Myfirst)[$i],
            size : $e._Mylast-$e._Myfirst
         ),
         ")"
      )
   )
}

The #array keyword tells the debugger that it should loop over the object for a certain number of iterations specified using the size variable, with the $i pseudo-variable specifying the element number. The other supported collection iteration constructs are #tree (which allows head, skip, size, left, and right variables to be defined) and #list (head, size, and next are specified).

In addition to the preview and children display settings that can be specified, it is possible to customize how strings are displayed by using the built-in text visualizer shown in Figure 4. The display setting for the ATL CComBSTR is shown below:

ATL::CComBSTR{
   preview  ([$e.m_str,su])
   stringview  ([$e.m_str,sub])
}

In both cases, the BSTR member variable is shown by using the $e identifier (which is a pseudo-variable for the object being displayed) followed by the m_str member variable. The difference between the preview and stringview settings is that the string format specifier – su instructs the debugger to display a string with double-quotes, and sub is a string with no quotation marks. Figure 4 shows the display differences.

Figure 4: Customizing stringview display

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read