c++debuggingwindbg

How do I get CDB to display the value of a std::filesystem::path?


I’m working on contributing to Descent 3. The pull request that I’m currently working on has a Windows-only bug. I would like to use a debugger in order to help me track down the bug.

As part of the debugging process, I want to be able to view the value of an std::filesystem::path variable. When debugging a program on Linux, I can run this GDB command in order to view the value of an std::filesystem::path:

(gdb) p example_path
$1 = filesystem::path "foo/bar/baz" = {[0] = "foo", [1] = "bar", [2] = "baz"}
(gdb) 

When debugging a program on Windows, how do I get CDB to do something similar?


I’ve tried a few things so far. First, I tried using the dv command, but it didn’t give me any useful information:

0:000> dv example_path
   example_path = class std::filesystem::path
0:000> 

I also tried using the ?? command. I tried to just evaluate the path itself:

0:000> ?? example_path
class std::filesystem::path
   +0x000 _Text            : std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >
0:000> 

When that didn’t give me any useful information, I tried calling the string() method, but that didn’t work:

0:000> ?? example_path.string()
Type does not have given member error at 'string()'
0:000> 

Finally, I tried drilling down into the _Text member that CDB told be about earlier, but I got stuck:

0:000> ?? example_path
class std::filesystem::path
   +0x000 _Text            : std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >
0:000> ?? example_path._Text
class std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >
   +0x000 _Mypair          : std::_Compressed_pair<std::allocator<wchar_t>,std::_String_val<std::_Simple_types<wchar_t> >,1>
0:000> ?? example_path._Text._MyPair
Type does not have given member error at '_MyPair'
0:000> 

Solution

  • To display the value of an std::filesystem::path, use CDB’s dx command:

    0:000> dx example_path
    example_path     [Type: std::filesystem::path]
        preferred_separator : 92 '\' [Type: wchar_t]
        [+0x000] _Text            : "foo\bar\baz" [Type: std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >]
    0:000> 
    

    Also, the strategy of using the ?? command in order to drill down into the path would have worked, but I misread the name of one of the members. It’s called _Mypair with a lowercase p, not _MyPair with an uppercase P:

    0:000> ?? example_path
    class std::filesystem::path
       +0x000 _Text            : std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >
    0:000> ?? example_path._Text
    class std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >
       +0x000 _Mypair          : std::_Compressed_pair<std::allocator<wchar_t>,std::_String_val<std::_Simple_types<wchar_t> >,1>
    0:000> ?? example_path._Text._Mypair
    class std::_Compressed_pair<std::allocator<wchar_t>,std::_String_val<std::_Simple_types<wchar_t> >,1>
       +0x000 _Myval2          : std::_String_val<std::_Simple_types<wchar_t> >
    0:000> ?? example_path._Text._Mypair._Myval2
    class std::_String_val<std::_Simple_types<wchar_t> >
       +0x000 _Myproxy         : 0x0000022e`a0b8c6b0 std::_Container_proxy
       +0x008 _Bx              : std::_String_val<std::_Simple_types<wchar_t> >::_Bxty
       +0x018 _Mysize          : 0xb
       +0x020 _Myres           : 0xf
    0:000> ?? example_path._Text._Mypair._Myval2._Bx
    union std::_String_val<std::_Simple_types<wchar_t> >::_Bxty
       +0x000 _Buf             : [8]  "봐ꂸȮ"
       +0x000 _Ptr             : 0x0000022e`a0b8bd10  "foo\bar\baz"
       +0x000 _Alias           : [8]  "???"
    0:000> ?? example_path._Text._Mypair._Myval2._Bx._Ptr
    wchar_t * 0x0000022e`a0b8bd10
     "foo\bar\baz"
    0:000>