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.

  • I'm very glad to see enhancements on the customized visualization front; I think this will be well-received.

    With that said, I do have a couple of suggestions:

    It would be most useful if we could store debugger visualization customizations as close as possible to the corresponding class/struct definitions, because the two need to be kept in sync; the .natvis file needs to be version controlled along with the source files.  Imagine that I check out a header and make a change to a struct; the system described in this post would appear to require that I now also check out and update a shared .natvis file at the solution level.  That's going to be very contentious in large projects with many developers.

    A better solution would be to have the .natvis be a sibling file to the class, so you'd have Foo.natvis alongside Foo.h and Foo.cpp.  An even better option would be to allow storing visualization hints as structured comments within the class definition itself.

    Another (probably more difficult) wish list item would be to allow linking a visualizer variable to the evaluation of a method call (probably only const methods with no parameters).  This would help when the logical state of an object isn't directly stored in its member variables.

  • @GregM: Regarding raw pointers in a std::vector, you can use the [Raw View] node for this purpose. When the children values are customized using a type visualizer, a [Raw View] node is automatically added (you can see this in the last screenshot above, it's been omitted from couple other screenshots for simplicity).

    Regarding rules on how a type visualizer applies to class hierarchies, you can find more information in the "Visualizer – Type Matching" section in the sample page (code.msdn.microsoft.com/Writing-type-visualizers-2eae77a2).

  • @Erik Olofsson, @Simon Buchan, @S. Colcord: Thanks for your comments and suggestions. Feel free to also submit these to Microsoft Connect (with as much detail as you would like). Your feedback will help us address your scenarios, issues in future updates.

  • Cagri, is this Raw View node new for VS2012?  If so, then that's great, thanks.

  • Rodney Dangerfield has been quoted as saying that if C++/CLI developers had been around 30 years ago, he would have felt like he actuallly got a decent amount of respect by comparison, so he wouldn't have had an act ;-).

    Eric

  • MikeK> I hope vs11 will ship with visualizers for most STL classes.

    I maintain visualizers for all STL classes that can be usefully visualized (in the stl.natvis that Cagri mentioned). If you think something's missing, or that a particular visualizer could be improved, let me know at stl@microsoft.com .

    Raffaele Rialdi> Any example for WinRT and COM types?

    The visualizers for collection.h's Vector/VectorView and Map/MapView "cheat" by delegating to the STL, through the wonderful ExpandedItem feature.

    fourbadcats> I see there are also .natstepfilter files to replace the NoStepInto regkey madness.

    I added std::forward<T>() and std::move() to that list.

    GregM> Will this allow us to customize the current visualizers, such as actually allowing us to see the raw pointers in a std::vector?

    In addition to VC11's [Raw View], in VC8/9/10/11 putting "foobar,!" into the Watch window (minus quotes of course) will disable the visualizers for foobar.

  • Any chance we can finally get visualizers for Xbox?

  • It is a solid improvement, but it would have been much nicer if this could be written in a real language(say python/lua) not some crappy XML psuedo language

  • nice.   i was just trying to muddle through the opaqueness that is autoexp.dat a few days ago, great to see this has been addressed!

  • std::array seems to be missing. Also, if you have an array of vectors, it only shows the first vector when you expand the array to look at _Elems.

  • @Andrew McDonald: Andrew, we couldn't see the issue here. Please report your issue at Microsoft Connect with the  code snippet you used (if possible) that didn't work. That would help us pinpoint the problem or verify that the issue has been fixed. Thanks.

  • Is it possible to create visualizers for a C++ class library that has a pimpl:ed public interface? In other words, can the expression contain method calls? For example if the Rectangle looked like this:

    class Rectangle

    {

    public:

     Rectange(int, int);

     ~Rectangle();

     int width() const;

     int height() const;

    private:

     void* pimpl;

    };

  • @foobar> No, the expression cannot contain method calls. For objects of your Rectangle class, the only way to get that information is by explicitly invoking the methods on the object in the watch window. Note that function evaluation is a dangerous operation which is why it's not supported in the natvis xml file. You can check out blogs.msdn.com/.../400794.aspx and the other articles linked from there for various issues with it. The posts are targeted towards function evaluation in managed code, but general points (and more) apply for native function evaluation.

  • Andrew McDonald: Are you using VC11 RC? I just verified in a VM that VC11 RC contains my rewrite of the STL visualizers, including std::array, and that array<int, 5> and array<vector<string>, 3> are correctly visualized.

    foobar: Note that you can write a visualizer for Rectangle that casts pimpl to the appropriate type before digging out various data members.

  • @Cagri Aslan: I appreciate the risks involved in allowing function execution while stopped in the debugger.  Nevertheless, it would still be a very useful capability.

    Here's a possibility:  What if the visualizer could handle having a debugger property bound to a method invocation, but required the user to deliberately click an 'Evaluate' icon to execute it?

    This would be functionally equivalent to going to the watch window and invoking the method there, but would create a much more streamlined experience for the user.

Page 2 of 3 (39 items) 123