2

When debugging with WinDbg I cannot see value of local std::string variables. I can see values of boolean variables but when hovering over a string variable or viewing it in Locals window, all I see is the type of the variable but not its actual value.

How can I see the value of a local std::string variable?

Thomas Weller
  • 43,638
  • 16
  • 101
  • 185
mkd156
  • 405
  • 3
  • 5
  • 16

3 Answers3

6

Despite being simple on the outside, std::string is a surprisingly complex type and WinDbg just doesn't have the smarts to display it in a more human-readable format.

Hovering over it in WinDbg shows something like this:

Tooltip in WinDbg of std::string

And, that's not helpful at all.

Luckily, the data is there, we just have to dig for it. In our case, the string's value is hiding in the _Bx member. We can get to it by running dt -r3 myString. This will recursively print the members of myString to the console (up to 3 levels).

0:000> dt -r3 myString
Local var @ 0x23fd90 Type std::basic_string<char,std::char_traits<char>,std::allocator<char> >
   +0x000 _Myproxy         : 0x00445638 std::_Container_proxy
      +0x000 _Mycont          : 0x0023fd90 std::_Container_base12
         +0x000 _Myproxy         : 0x00445638 std::_Container_proxy
            +0x000 _Mycont          : 0x0023fd90 std::_Container_base12
            +0x004 _Myfirstiter     : (null) 
      +0x004 _Myfirstiter     : (null) 
   +0x004 _Bx              : std::_String_val<std::_Simple_types<char> >::_Bxty
      +0x000 _Buf             : [16]  "test1234"
      +0x000 _Ptr             : 0x74736574  "--- memory read error at address 0x74736574 ---"
      +0x000 _Alias           : [16]  "test1234"
   +0x014 _Mysize          : 8
   +0x018 _Myres           : 0xf
   =00a00000 npos             : 0x905a4d

It took some work, but we got there.


Some things to keep in mind:

  1. Understand that you are looking under the hood of the implementation of a library type. This can (and will) change at any time. The implementation in my screenshots is from VS2015 and will likely differ from other versions.
  2. The string's value is tucked away in the _Bx union as a means to implement the Small String Optimization (SSO). When the string is short enough, it will be stored in _Bx._Buf, otherwise, it will be allocated on the free store and a pointer to it stored in _Bx._Ptr. Don't be shocked if you see what looks like garbage data in one of them, but valid data in the other.
  3. This isn't a problem in Visual Studio's debugger because they have ways of visualizing types and data structures. This is done with .NATVIS files which are provided by Visual Studio for common types like std::string.
Community
  • 1
  • 1
Sean Cline
  • 6,603
  • 1
  • 31
  • 49
2

paste this line in a txt file and use $$>a< to execute the script this will dump all the Local std::string->c_str() whose length are > 16

!for_each_local ".printf \" @#Local = %ma\\n\" , poi( @#Local )"

for strings that are shorter than 16 use da <name>

enter image description here

blabb
  • 7,524
  • 1
  • 14
  • 23
  • You said: "the script this will dump all the Local std::string->c_str()", but the script does not distinguish between strings and other locals, so any other type of local variable might generate incorrect output, wouldn't it? – Thomas Weller Aug 13 '15 at 07:50
  • 1
    yes as there is no universal correct method and the internal structures of std::string often are not same across vs versions (see the display by sean cline where there is a container Myproxy and the Bx is at 0x+4 not at 0x0 which the script assumes will also provide errenous result but it works in most of the case and when there is an error you get a type not fuund , foo is not a member of blah etc which will provide a direction to take) – blabb Aug 14 '15 at 04:11
0

Try the "View Locals" icon or ALT+3, it should show at least the address.