Using [] operator with unordered_map in gdb give unresolved operator

Viewed 6841

I have a C++ code where I am instantiating an unordered_map and then printing it's values using cout. This works fine. But, when I try to run this in gdb and print the values of the unordered_map, this gives me error. Below, is the code snippet:

  std::unordered_map<std::string,int> mymap = {
                      { "Mars", 3000},
                      { "Saturn", 60000},
                      { "Jupiter", 70000 } };

    std::cout<< mymap.at("Mars");
    std::cout<< mymap["Mars"];

Both the cout statements above print the unordered_map value for key "Mars". However, when I use gdb and then try using below statements to print the value of mymap at key "Mars", I get errors.

(gdb) print mymap.at("Mars")
Cannot resolve method std::unordered_map<std::basic_string<char, 
std::char_traits<char>, std::allocator<char> >, int, 
std::hash<std::basic_string<char, std::char_traits<char>, 
std::allocator<char> > >, std::equal_to<std::basic_string<char, 
std::char_traits<char>, std::allocator<char> > >, 
std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, 
std::allocator<char> > const, int> > >::at to any overloaded instance

(gdb) print mymap["Mars"]
Cannot resolve function operator[] to any overloaded instance

I do not get what is wrong when I use gdb.

I have tried using whatis mymap, in gdb, to see if mymap is present in current context and it gives that it is present. Also, I tried initializing an int variable and printing it in gdb and it prints it. I do not understand what is the problem with unordered_map.

I am using below statement to generate executable

gsrivas4@TitanX01:~/lcode1$ g++ -std=gnu++11 -O0 -g test1.cpp -o test1.out
1 Answers

The problem you are facing is that std::unordered_map<std::string,int>::at(key) expects a key of type std::string, not a const char* literal. This means that you'd like to create a temporary std::string object, before passing it to at().

Creating a temporary object from within GDB does not work well for me, and I may be missing something but this is what I get:

(gdb) p std::string("Mars")
A syntax error in expression, near `"Mars")'.
(gdb) p 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)'("Mars")
$9 = -161888904

So it does not seem possible to construct an std::string object inside GDB without some additional C++ code, so just add to your C++ code:

std::string make_string(const char *x)
{
        return x;
}

And now everything works:

(gdb) p mymap.at(make_string("Mars"))
$1 = (std::unordered_map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >::mapped_type &) @0x60005e5f0: 3000
(gdb) p mymap.at(make_string("Jupiter"))
[New Thread 14608.0x16f4]
$2 = (std::unordered_map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >::mapped_type &) @0x60005e650: 70000

But

(gdb) p mymap[make_string("Jupiter")]
Could not find operator[].

This does not work because it was never instantiated. What your code instantiated by:

std::cout<< mymap["Mars"];

was T& operator[]( Key&& key ); which is tricky to invoke from GDB. Had you instantiated T& operator[]( const Key& key ); instead, then things would have fared better.

The solution: instantiate the operator[](const std::string &) variant in your C++ code. So here is the new code:

std::string make_string(const char *x)
{
        return x;
}

int main()
{
 std::unordered_map<std::string,int> mymap = {
                      { "Mars", 3000},
                      { "Saturn", 60000},
                      { "Jupiter", 70000 } };

    std::string mars{"Mars"};
    std::cout<< mymap.at(mars);
    std::cout<< mymap[mars];
}

With this, debugging becomes possible:

print mymap.at(make_string("Jupiter"))
print mymap[make_string("Jupiter")]

just work.

Related