Monday 19 July 2010

Customising the Visual studio debugger

If you delve deep into the bowels of your install of visual studio you might come across autoexp.dat. "What does this file do?" you might ask. Well, you're in luck.

The default behaviour of the windows that display the contents of your variables (autos/locals/watch) in visual studio is, if it's a basic type, such as an int or a float, to display it as is.
If it's a struct or a class, then allow the user to navigate it's structure revealing all variables contained within.

The autoexp.dat file allows for the customisation of this process (and if you look in the file you'll notice Microsoft has already pre-populated it with lots of entries, predominantly for things in the c++ standard library).

Why would you want to customise something if the default behaviour is perfectly acceptable?
Well, here's an example. Say you've got a 3D Maths Vector class which contains 3 floats: X, Y and Z. It's also got all the usual functions you need for doing all the various things you might with a vector, such as dot and cross products etc.
You might then think of a great idea to include some common vectors as static const members to the class. These could include a definition for "UP" where you have Y=1, or another could simply be "ZERO" for when you want a comparison but don't want the overhead [or hassle] of creating a new instance.

It's a good plan, but has the unfortunate side effect of bloating the debugger display to showing you all of your constants every time you expand a vector variable.

In steps autoexp.dat, and here's a simple example of how to write a definition:

;-----------------------------------------------------------
; Vector3d
;-----------------------------------------------------------
Vector3d{
  preview
  (
    #(
      "[",
      $e.x,
      ",",
      $e.y,
      ",",
      $e.z,
      "]"
    )
  )
  children
  (  
    #(
      X                 : $e.x,
      Y                 : $e.y,
      Z                 : $e.z,
      [actual members]  : [$e,!]
    )
  )
}

First things first, any line that begins with a ";" is treated as a comment and ignored.

Next you have the name of the type you wish to define. In this case it's my 3d vector class. This also supports templates, so "SomeType<*>" is perfectly acceptable, as is template specialisation, e.g. "SomeType".

You'll notice the opening brace "{" is immediately after the type rather than on it's own line. This is because the parser is very unstable and prone to breaking easily. If there is any space between the type and the brace, it just doesn't work.

Next you have your categories. In the example I've given there's "preview" and "children", but there's also "stringview" available, should you require it.

Preview defines what is displayed in the value box for the main type. In this case it will be "[X,Y,Z]" where X, Y and Z are floating point numbers. $e means display in scientific notation should the number be large or small enough to warrant. If you take a look at the top of the autoexp.dat file, you will notice that you have a choice of several different types. $f for instance should allow you to display the number as a standard floating point and never factorise into scientific notation, though, again for me at least, the parser preferred to crash rather than work with anything other than $e.

The "#()" notation simply means here is a comma delimited list of values.

The Children section defines what should be displayed when the user expands the variable. As you can see I include the three members of the vector and an escape clause, if for some reason I need to see the original default formatting of the variable.

I learned everything myself from this wonderful post over at virtualdub.org.

No comments:

Post a Comment