1

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?

lksj
  • 49
  • 7
  • I'm afraid this is not in the cards. gdb's ability to interpret C++ containers is quite limited. C++ is just too complicated, and only a C++ compiler can fully understand a C++ program. gdb is not a C++ compiler. – Sam Varshavchik Nov 24 '21 at 11:41
  • @SamVarshavchik Ah.. then.. can I get a specific value of map object only in "p si" and I try to find what I want to get? – lksj Nov 24 '21 at 11:45
  • @SamVarshavchik and.. could you tell me what is the best c++ debugger for ubuntu environment? – lksj Nov 24 '21 at 11:49
  • try things like "(gdb) print si" first, to see if and how it prints whole map then look further what the problem is. GDB has improved ... versions 7+ (and that is like for decade) your's is 9.x its C++ support is quite good. – Öö Tiib Nov 24 '21 at 13:39
  • I don't have any other debugger to recommend, and recommendations are not appropriate for Stackoverflow. I always used `gdb` on Linux. `gdb` is available everywhere, so I know that it will always be available no matter which Linux distribution I am using. – Sam Varshavchik Nov 24 '21 at 13:48
  • @ÖöTiib Thanks your reply. But I know that already. And that code is just test code. However in my actual code, my std::map object has the number of 10,000 elements.. So I need index based method. Thanks again! – lksj Nov 25 '21 at 00:59
  • But index of your map is std::string not string literal. Maybe accepted answer of this question helps you https://stackoverflow.com/questions/7429462/creating-c-string-in-gdb – Öö Tiib Nov 25 '21 at 07:36
  • @ÖöTiib Thank you very much! Although your link is not helpful directly for me, but I could find solution in related links! The links are https://stackoverflow.com/questions/42462860/calling-stdbasic-string-in-gdb?noredirect=1&lq=1 and https://stackoverflow.com/questions/427589/inspecting-standard-container-stdmap-contents-with-gdb. I'm verry happy!! Thank you very much!! – lksj Nov 25 '21 at 10:05
  • 1
    @lksj If you figured out a solution you may want to post it as an answer (click "post your answer" button) so future readers can benefit from it. – user202729 Dec 04 '21 at 08:03

1 Answers1

0

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
lksj
  • 49
  • 7