Visual Studio Data Visualization: Debugging Natvis

Microsoft’s Visual Studio has introduced helpful features to improve data visualization when debugging. This presents a bit of help to ensure you are in the correct ballpark when starting, ie starting out with new technologies can be a pain, this may help.

This simple bit of code illustrates how natvis can look during debugging:

NativisCpp

Notice the pinned item shows the next entry in the list, as well as that entries value. VS actually handles the recursion – very nice.

Here is the natvis file. It’s simply added to the project as a project file and you perform minor edits. Links at end of this article.

NavisXml

Finally, the real power is in the Watch window:

NatvisWatch

Notice how ‘myData’ comes 1st in the list. There are many examples whereby natvis can be used to re-order data presentation to solve your particular problem. Very nice.

So this is the happy path. Joy. How do you know it’s working? Several folks have struggled to get natvis properly configured. Several suggestions have been tossed out to change debugging options, etc.

So let’s create an error situation and see what you should see. The natvis xml will be intentionally fouled up:

NatvisErrorInXml

Now the output window will display the error:

Natvis: C:\Users\DavidHa\Documents\Visual Studio 2015\Projects\NatvisExample\NatvisExample\NatvisFile1.natvis(4,30): Successfully parsed expression 'myData,c' in type context 'DchEntry'.
Natvis: C:\Users\DavidHa\Documents\Visual Studio 2015\Projects\NatvisExample\NatvisExample\NatvisFile1.natvis(4,43): Error: identifier "nextEntryXYZ" is undefined
 Error while evaluating 'nextEntryXYZ' in the context of type 'NatvisExample.exe!DchEntry'.
Natvis: C:\Users\DavidHa\Documents\Visual Studio 2015\Projects\NatvisExample\NatvisExample\NatvisFile1.natvis(3,4): Ignoring visualizer for type 'DchEntry' labeled as 'DchEntry' because one or more sub-expressions was invalid.

Now we have confirmation that natvis in this project is properly configured! Two items in particular seem to be necessary:

  1.  What I’ve found is that Tools->Options->Debugging->Ouput Window.NatvisDiagnosticMessages option needs to be set to verbose.
  2. Also, there is a registry key that needs to be created:
[HKEY_CURRENT_USER\Software\Microsoft\Visual Studio\14.0_Config\AD7Metrics\ExpressionEvaluator\{3A12D0B7-C26C-11D0-B442-00A0244A1DD2}\{994B45C4-E6E9-11D2-903F-00C04FA302A1}]

Value Name: LoadInShimManagedEE

0 means new MC++ EE is ENABLED

1 means new MC++ EE is DISABLED (default value)

 

That’s it. This gets past my pain points of initial configuration. Below are several links regarding this topic.

Create custom views of native objects

Debug Visualizers in Visual C++ 2015

Natvis for C++/CLI Available to Preview in VS2015 Update 2 – this has the info on the reg key.

Using C++ debug visualizers in VS2015

Visual Studio Data Visualization: Debugging Natvis

Better Legacy C++ Code with Tools

A very simple typo resulted in a bug:

CString myTest(“foo”);
if( myTest.find(“o” < 0))  //should be find(“o”) < 0
{
//never gets here, regardless of find() test contents
}

 

Notice how the simple mis-placement of the ) on find() leads to this error, albeit compiled correctly. The compiler is actually converting this to pointer arithmetic and the address of the “o” string is always something and cannot be less than zero; hence this is always false. Switching to std::string yields the same:

 

#include <string>
int badChar()
{
std::string test(“abc”);
if (std::string::npos != test.find(“123” < 0)) return 1;
return foo; //returns 0 (zero)
}

 

This test was done w/ Visual Studio 2015 and default warning level of 3. So what can be done?
Running Cppcheck yields a weak warning:
(style) A pointer can not be negative so it is either pointless or an error to check if it is.

 

It’s weak in that errors should be more aggressively pointed out to err on the side of safety. But let’s not loose sight of the positive: it is helpful.

 

Alternatively, if the warning level is set to 4, a warning is generated:
‘<‘ : logical operation on address of string constant

 

This is good news!

 

If one is really pedantic, try compiling your code against a totally different compiler, such as gcc. On my Mac, this won’t even compile. However, using std::string::npos makes the original error even more difficult. It’s completely illogical and hurts to even visually scan it.

 

So then, getting back to the main point: what tools or actions are available to help ensure legacy code is great?
  1. Temporarily compile with more advanced compiler versions
  2. Temporarily compile with stronger warnings
  3. Use tools such as Cppcheck to 2x check your code
  4. Try compiling with a completely different compiler
  5. Limit use of platform or library data types such as ‘CString’ to where it’s absolutely needed. Use std::string as much as possible.

 

Today we have great tools: SSD drives, RAM, multi-processors, caches, etc. These resources give us a great opportunity to experiment, validate & grow while doing your daily work. The only thing your team will notice is higher quality work.

 

To quote David Cutler: “If you don’t put bugs in, you don’t have to take them out.”

Better Legacy C++ Code with Tools