10

For debugging, I need to see the content of a map (std::unordered_map or std::map), which the Eclipse CDT debugger does not give me in a readable form, e.g. {1: 2, 3:4, ...}

What is the best way to inspect the content of a map while debugging?

Do I have to go back to debugging with print-statements? If yes, how would a concise macro or function look like that prints the content of any map as a string?

clstaudt
  • 21,436
  • 45
  • 156
  • 239

2 Answers2

1

Do I have to go back to debugging with print-statements? If yes, how would a concise macro or function look like that prints the content of any map as a string?

I don't know if you do or not - I don't use Eclipse, but printing a map is very easy:

template <typename K, typename V>
std::ostream& operator<<(std::ostream& os, const std::map<K, V>& m)
{
    os << "{ ";
    for (typename std::map<K, V>::const_iterator i = m.begin(); i != m.end(); ++i)
    {
        if (i != m.begin()) os << ", ";
        os << i->first << ": " << i->second;
    }
    return os << " }";
}

Then you can just use << my_map. Note though that in a large code base there's a chance that someone else will have had the same "bright" idea, so you might want to put your helper function in your own namespace, or give it a more localised name. Things like the choice of surrounding "{ " and " }" and ", " separators are arbitrary and may not suit all users - some may want automatic string quoting/escaping etc., so putting this in a global namespace would be dubious at the best of times, and in this case it might even be reserved for possible inclusion in a future C++ Standard or something - after all, it's kind of liking adding your own names into the std:: namespace. Check the Standard if you care.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • This would be a solution, but when I compile this code I get the error: `/usr/local/Cellar/log4cxx/0.10.0/include/log4cxx/helpers/messagebuffer.h:190:47: error: cannot bind 'std::basic_ostream' lvalue to 'std::basic_ostream&&'` – clstaudt Dec 17 '12 at 10:44
  • It's even simpler with [C++11 range based for loops](http://en.cppreference.com/w/cpp/language/range-for), as shown for example in [this answer](http://stackoverflow.com/a/6963910/440558). – Some programmer dude Dec 17 '12 at 10:49
  • 1
    @cls: you're not getting a match on this template, and that error's coming from another candidate function. If you put this in a different namespace from the calling code, then it won't be found. You could add `using Whatever_Namespace_It_Is_In::operator<<;` before the code that wants to use it. – Tony Delroy Dec 18 '12 at 01:36
  • @JoachimPileborg: Seeing `m.begin()` in the loop control and separator test has a nice consistency; given C++11 I'd just simplify `typename std::map::const_iterator` to `auto`. With ranged based for, what would you recommend - `&kv != &*m.begin()`, or a separate `bool first = true; ... if (first) first = false; else os << ", "` / `size_t i = 0; ... if (i++)`? – Tony Delroy Dec 18 '12 at 01:44
1

GDB can be extended with Python, and there is an API for pretty printing.

There are many pretty printers for C++ available, like for example this one.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • This would be the optimal solution. I'd like to try this, but I cannot get a python-enabled gdb to run in Eclipse (see this question: http://stackoverflow.com/questions/13913818/how-to-get-a-codesigned-gdb-on-osx) – clstaudt Dec 17 '12 at 12:15