Debugger Type Visualizers for C++ in Visual Studio 2012

Debugger Type Visualizers for C++ in Visual Studio 2012

Rate This
  • Comments 39

 In Visual Studio 2012, one of the new features for C++ developers is the new native type visualization framework (natvis) added to the debugger which allows customizing the way data types are displayed in debugger variable windows (e. g. autos, watch, locals, and data tips). For those who are familiar with the autoexp.dat file that has been used in earlier versions of Visual Studio, this new visualization framework supersedes that and offers xml syntax, better diagnostics, versioning and multiple file support.

To illustrate how type visualizers help make it easier to inspect objects, the following screenshot shows how a std::vector<int> is displayed in the debugger without any type visualizers:

                  

The view without type visualizers is not user-friendly and hard to read. You cannot easily see the size or the elements of the vector. Visual Studio ships with type visualizers for common data types such as std::vector and the default view for a std::vector using type visualizers is much more useful:

 

 

Creating a type visualizer for a custom data type

If you have a custom data type you can easily override Visual Studio’s default view of it using this framework and make it easy to inspect objects of that type. To demonstrate how you can do this, let’s go through the process of creating one for the simple rectangle type shown in the code snippet below (the dummy code that uses it is also included):

struct Rectangle

{

    int height;

    int width;

};

 

int _tmain(int argc, _TCHAR* argv[])

{

    Rectangle myRectangle = { 3, 4 };

    Rectangle myRectangle2 = { 4, 4 };

    return 0;

}

 

The debugger’s default view of the “myRectangle” variable which we are going to customize is as follows:

 

 

Type visualizers for C++ types are specified in .natvis files. A natvis file is simply an xml file (with .natvis extension) that contains visualization rules for one or more types. At the start of each debugging session, Visual Studio processes any natvis files it can find in the following locations:

  • -         %VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers (requires admin access)
  • -         %USERPROFILE%\My Documents\Visual Studio 2012\Visualizers\
  • -         VS extension folders

 

As the first visualizer for the rectangle type, create a new file called “rectangle.natvis” containing the following xml (explained further below) and save it in “My Documents\Visual Studio 2012\Visualizers” folder.

 

<?xml version="1.0" encoding="utf-8"?>

<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">

    <Type Name="Rectangle">

        <DisplayString>A rectangle with height = {height} and width = {width}</DisplayString>

    </Type>

</AutoVisualizer>

 

After the file is saved, start debugging the code snippet we have for the type and view the ‘myRectangle’ variable in the watch window. The debugger now displays the object as:

 

 

 

To explain the xml snippet in the natvis file, each Type element represents a visualizer entry for a type whose fully qualified name is specified in the Name attribute. DisplayString element customizes the string shown in the value column for the type. It accepts a mixture of arbitrary strings and expressions. Everything inside curly braces ({height}, {width} above) is interpreted as an expression and gets evaluated by the debugger.

Let’s assume you would like to enhance this view when the rectangle is actually a square and display something different. You can use the Condition attribute, which is available for many visualizer elements, to have if-else logic in the visualization entry. Add the following highlighted line to the visualizer entry and save the file:

<?xml version="1.0" encoding="utf-8"?>

<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">

    <Type Name="Rectangle">

        <DisplayString Condition="height == width">This is a square with sides of {height}</DisplayString>

        <DisplayString>This is a rectangle with height = {height} and width = {width}</DisplayString>

    </Type>

</AutoVisualizer>

 

Note that it is NOT necessary to restart Visual Studio for it to pick up the changes to a visualizer. Once you start the debugger and add ‘myRectangle’, ‘myRectangle2’ variables to the watch window, you can see a different string is shown for a rectangle object that is actually a square:

 

 

Just as you can customize the value of the variable shown in the value column, you can also customize the view of the child elements when the variable is expanded in the debugger windows. Let’s say you would like to see the area of a rectangle in addition to its height and width during debugging. The Expand node, which allows you to define child elements for a type, can be used for this purpose. Add the highlighted section below to the visualizer entry and save the file:

<?xml version="1.0" encoding="utf-8"?>

<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">

    <Type Name="Rectangle">

        <DisplayString Condition="height == width">A square with sides of {height}</DisplayString>

        <DisplayString>A rectangle with height = {height} and width = {width}</DisplayString>

        <Expand>

            <Item Name="height">height</Item>

            <Item Name="width">width</Item>

            <Item Name="area">height * width</Item>

        </Expand>

    </Type>

</AutoVisualizer>

 

As you can guess, each Item node defines a single child element whose name is given by the Name attribute and whose value is given by the expression in the node text. This is the updated view with the area element added:

 

More information

This blog post covers just a little bit of what you can do with the new native type visualization framework in the Visual Studio debugger. To learn more about it you can check out our sample page on msdn where we have more examples, xml syntax reference, instructions on turning on diagnostics and deploying visualizers via VSIX packages.

 

 

Cagri Aslan, Developer on the Visual Studio Debugger team.

  • Will there be an equivalent to the "_vcee_autoexp" environment variable from VS2010, which allowed autoexp extensions to reside in arbitrary locations? This is a very useful feature when sharing extensions on a team using revision control systems like Perforce or Subversion.

  • You can put them next to the solution file and they will apply onto to it.

  • While the far nicer format is appreciated, ... why aren't these customizable at the project or solution level? You know, the one place where it makes *sense* to define these? Either a project setting listing .natvis files or just looking for any in the project dir would be enough to turn this from a useless feature to an incredibly useful feature to me....

  • This is wonderful. I hope vs11 will ship with visualizers for most STL classes.

  • Talking of coincidence, I was thinking about this yesterday. I just hope the visualizer language is more expressive?

  • Would it be possible to follow pointers across loaded DLLs? When debugging our current project expanding pointers to another library in auto/locals/watch window doesn't work. Also the autoexp.dat cannot see through.

  • Will you still be able to use the EEAddin feature? We rely on this for some date/time conversion visualisers

  • Hey, Cagri,

    Looks good.  We've always had trouble getting debugger visualizers to work well with our C++/CLI code.  Has progress been made there with this update?

    Thanks,

    Eric

  • I have been testing these extensively and have been meaning to submit my list of bugs to connect for a couple of months now.

    Some comments:

    * They are incredibly slow especially with long template names. It can take upwards of 30 seconds when I break into the debugger. From the debugger it looks like the problem is concatenating names by + instead of +=

    * It's unfortunate that you choose xml instead of JSON or something that does not require you to escape < and > which is used kind of often in templates :)

    * It would be nice if LegacyAddin could work with StringView. Would be especially useful for parsed content such as XML nodes.

    * You should really be able to link these into pdb files so when you look at old crash dumps you get the correct version if your structures have changed.

  • Any example for WinRT and COM types?

  • First, it's nice to see a supported mechanism beyond reverse-engineering autoexp.dat.

    There does not appear to be any progress for C++/CLI code. In my initial tests, the visualizers do not seem to be used when debugging in Mixed Mode, even if I'm debugging in a file built without /clr. This makes me sad and a little bit mad - C++/CLI devs get the shaft..again.

    I see there are also .natstepfilter files to replace the NoStepInto regkey madness. Let's pray those will work for Mixed mode...

  • To follow-up my own tests: more bad news for C++/CLI devs.  

    The .natstepfilter files are ignored when debugging in Mixed mode. Even in code built without /clr. Since this is all the time for us, this really sucks.

  • @MikeK, @Raffaele Rialdi: Under %VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers folder you can look at "stl.natvis" file for STL examples, and "winrt.natvis" file for WinRT examples.

  • Will this allow us to customize the current visualizers, such as actually allowing us to see the raw pointers in a std::vector?  Will it also apply to base classes that don't add any data, just functions?  Currently, we have to expand down to the base class to get the actual data, which makes the tooltips less useful.

  • @BShatner: Yes, the documentation for addin options you'll have is yet to come.

Page 1 of 3 (39 items) 123