.NET Zone is brought to you in partnership with:

Sasha Goldshtein is a Senior Consultant for Sela Group, an Israeli company specializing in training, consulting and outsourcing to local and international customers.Sasha's work is divided across these three primary disciplines. He consults for clients on architecture, development, debugging and performance issues; he actively develops code using the latest bits of technology from Microsoft; and he conducts training classes on a variety of topics, from Windows Internals to .NET Performance. You can read more about Sasha's work and his latest ventures at his blog: http://blogs.microsoft.co.il/blogs/sasha. Sasha writes from Herzliya, Israel. Sasha is a DZone MVB and is not an employee of DZone and has posted 203 posts at DZone. You can read more from them at their website. View Full User Profile

Displaying and Searching std::vector Contents in WinDbg

07.25.2013
| 2222 views |
  • submit to reddit

WinDbg has never been very good at visualization. While Visual Studio has always had autoexp.dat, and as of late also native debugger visualizers, WinDbg users had to settle for dumping memory areas and searching memory to identify patterns.

On the other hand, Visual Studio does not offer any automation opportunities today if you’re looking to simplify your debugging process. You can’t write macros anymore as of Visual Studio 2012. WinDbg continues to offer scripting support so you can automate any mundane debugging tasks you encounter. If you make it past the initial learning curve and master WinDbg scripts, you can almost guarantee better and faster results than your colleagues who traverse objects by hand in Visual Studio.

There are some decent tutorials online that can guide you through the basics of WinDbg scripting, and the built-in documentation (debugger.chm) has some nice scenarios as well. In this post, I’d like to show you a simple script that searches std::vector instances for objects that match a specific criterion, and then displays them.

Here’s how you could use this script. Suppose you have a vector of complex objects of type point. The pointtype, in turn, has a field data, which has a field called z of type int. You’re looking for points whose data.zfield is equal to 0. Here you go:

0:000> $$>a< traverse_vector.script my_points ".block { .if (@@(@$t0->data.z) == 0) { ?? @$t0 } }" 

struct point * 0x0129e4d0 
  +0x000 x  : 0n0 
  +0x004 y  : 0n0 
  +0x008 data  : extra_data 

The script passes the $t0 pseudo-register to the command block for each element of the vector. In the above command block, the .if statement evaluates the provided expression as a C++ expression (the @@operator forces the C++ expression evaluator), and, if it is true, displays the current element by using the ??operator. The ?? operator simply displays a C++ expression.

Here’s the script with some comments:

$$ save pointer to first element (current element) 
r? $t0=${$arg1}._Myfirst

$$ save pointer to last element 
r? $t1=${$arg1}._Mylast

$$ save first forever 
r? $t2=@$t0

.while (@$t0 != @$t1) 
{ 
  .if (${/d:$arg2} == 0) { 
  $$ display element, no command provided 
  .printf "index %d, address %p\n", @@(@$t0 - @$t2), @$t2 
  ?? @$t0 
  } .else { 
  ${$arg2} 
  }

  $$ advance current element 
  r? $t0=@$t0 + 1 
}

The initial challenge is just getting through all the vector elements. This relies on the fact that vectors have_Myfirst and _Mylast members. Once that’s done, you can run arbitrary commands on the vector contents, print the elements, filter them, store them in a file, and so on.

I am posting short links and updates on Twitter as well as on this blog. You can follow me: @goldshtn

Published at DZone with permission of Sasha Goldshtein, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)