Friday, November 24, 2006

Visual Studio 2005 and Tracepoints

Tracepoints in Visual Studio 2005 are such a great debugging tool. Here's a summary of some of the useful things I've picked up relating to tracepoints. (At the moment, I've only used tracepoints in C#. Some points I bring up below relate to the .NET Framework, so will not work with unmanaged C++.)


Inserting a tracepoint

Two methods I know of:

  • Right-click the source line and select Breakpoint / Insert Tracepoint
  • Right-click an existing breakpoint and select When Hit and check Print a message when the dialog is displayed.

Either way, you'll see the following dialog (click for a better view):

Once you press OK, you'll see a diamond marker in the code:


Messages

Information added to the Print a message textbox is shown in the Output window. You could do this with in-code trace messages of course, but the beauty of using tracepoints is the code does not need to be edited (requiring a re-compile and possibly introducing a bug) and the message can be changed at any time during a debugging session.

Text entered directly into the message textbox can be a simple text message ("I've entered MyMethod"), contains special keywords ("Function: $FUNCTION") or expressions ("MyVariable = { MyVariable }").

The special keywords are (most shown in the explanatory text on the dialog):

  • $ADDRESS – the current instruction
  • $CALLER – previous function name
  • $CALLSTACK – the call stack
  • $FUNCTION – the name of the current function
  • $PID – the process ID
  • $PNAME – the process name
  • $TID – the thread ID
  • $TNAME – the thread name

There are two additional keywords not shown in the dialog

  • $FILEPOS – the current file position
  • $TICK – the CPU tick count in hexadecimal

There is no control over the output, so $FUNCTION contains the full signature including the namespace, classname and the types of any parameters.

Text in braces ('{' and '}') is evaluated. This can contain any code, so you can have something like:

  • Time: { DateTime.Now.ToLongTimeString() }

Yes, you can reference various classes from the .NET Framework. Or you could call a function or method:

  • Function returns: { MyMethod() }

So, using something like:

Func: $FUNCTION, Time: { DateTime.Now.ToLongTimeString() }, zoom: { zoom }

Will show up in the Output window every time this code is encountered:

Func: Keima.SetZoomLevel(int), Time: "16:31:55", zoom: 1
Func: Keima.SetZoomLevel(int), Time: "16:31:59", zoom: 3
Func: Keima.SetZoomLevel(int), Time: "16:32:02", zoom: 5
Func: Keima.SetZoomLevel(int), Time: "16:32:17", zoom: 9
Func: Keima.SetZoomLevel(int), Time: "16:32:20", zoom: 11

I've found a few restrictions:

  • Everything is output to a single line in the Output window (although $CALLSTACK outputs to multiple lines – adding '\n' etc doesn't help).
  • The messages only go to the Output window. It would have been nice to output to a file.

Managing tracepoints

The best way to manage tracepoint is to use the normal Breakpoints window (chord: Ctrl-D, B).

You can right-click a tracepoint to disable it or convert a breakpoint into a tracepoint (by selecting When Hit).

No comments: