Search code examples
c++gdbstdmap

How can I get specific std::map value with indexing while using gdb for debuggin c++ code?


I use Ubuntu 20.04-LTS with WSL(Windows Subsystem Linux), GDB version is 9.2, and I builded my c++ code with c++11.

I tried to access std::map's value with index in GDB, however GDB showed error message "Invalid cast".

My code is same for below

#include <iostream>
#include <map>
#include <string>

using std::cout;
using std::map;
using std::string;
using std::to_string;

int main()
{
    map<string, int> si;

    for(int i = 0; i < 10; ++i)
    {
        si[to_string(i)] = i;
    }

    for(int i = 0; i < 10; ++i)
    {
        cout << si[to_string(i)] << "\n";
    }
}

And, in GDB

GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ctest...
(gdb) l main
6       using std::map;
7       using std::string;
8       using std::to_string;
9
10      int main()
11      {
12              map<string, int> si;
13
14              for(int i = 0; i < 10; ++i)
15              {
(gdb) l 15
10      int main()
11      {
12              map<string, int> si;
13
14              for(int i = 0; i < 10; ++i)
15              {
16                      si[to_string(i)] = i;
17              }
18
19              for(int i = 0; i < 10; ++i)
(gdb) b 18
Breakpoint 1 at 0x2579: file ctest.cpp, line 19.
(gdb) r
Starting program: /home/lksj/ctest

Breakpoint 1, main () at ctest.cpp:19
19              for(int i = 0; i < 10; ++i)
(gdb) p si["1"]
Invalid cast.
(gdb)

How can I access the std::map object value directly with index in GDB?


Solution

  • You first write the below code in the ".gdbinit" file.

    define newstr
    set ($arg0)=(std::string*)malloc(sizeof(std::string))
    call ($arg0)->basic_string()
    # 'assign' returns *this; casting return to void avoids printing of the 
    struct.
    call (void)( ($arg0)->assign($arg1) )
    end
    
    define delstr
    call ($arg0)->~basic_string(0)
    #                           ^
    call free($arg0)
    set ($arg0)=(void*)0
    end
    

    And then write the below function in your c++ code.

    void indexing_map( map<string,[type]> & m, string i )
    {
        cout << m[i] << "\n";
    }
    

    Now, all things are ready. You just execute gdb for debugging your code with the

    newstr $foo [any string of map of the key]
    

    For example,

    example.cpp

    #include <iostream>
    #include <unordered_map>
    #include <string>
    
    using std::cout;
    using std::unordered_map;
    using std::string;
    
    void indexing_map(unordered_map<string, int> &m, string i)
    {
       cout << m[i] << "\n";
    }
    
    int main()
    {
        unordered_map<string, int> st_in;
        st_in["1"] = 1;
        st_in["2"] = 2;
        st_in["3"] = 3;
    
        indexing_map(st_in, "1");
    
        return 0;
    }
    

    and gdb

    (gdb) b 25
    Breakpoint 1 at 0x28d6: file ctest.cpp, line 25.
    (gdb) r
    Starting program: /home/user/ctest
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    
    Breakpoint 1, main () at ctest.cpp:25
    25          st_in["3"] = 3;
    (gdb) newstr $foo "1"
    (gdb) call indexing_map(st_in , *$foo)
    1