Over a million developers have joined DZone.
Platinum Partner

Displaying and Searching std::vector Contents in WinDbg

· Agile Zone

Reduce testing time & get feedback faster through automation. Read the Benefits of Parallel Testing, brought to you in partnership with Sauce Labs.

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 { 

  $$ 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

The Agile Zone is brought to you in partnership with Sauce Labs. Discover how to optimize your DevOps workflows with our cloud-based automated testing infrastructure.


Published at DZone with permission of Sasha Goldshtein , DZone MVB .

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}