Tuesday, March 15, 2011

Inspecting standard container (std::map) contents with gdb

Supposing to have something like this:

#include <map>
int main(){
    std::map<int,int> m;
    m[1] = 2;
    m[2] = 4;
    return 0;
}

I would like to be able to inspect the contents of the map running the program from gdb.
If I try using the subscript operator I get:

(gdb) p m[1]
Attempt to take address of value not located in memory.

Using the find method does not yield better results:

(gdb) p m.find(1)
Cannot evaluate function -- may be inlined

Is there a way to accomplish this?

From stackoverflow
  • I think there isn't, at least not if your source is optimized etc. However, there are some macros for gdb that can inspect STL containers for you:

    http://sourceware.org/ml/gdb/2008-02/msg00064.html

    However, I don't use this, so YMMV

    Paolo Tedesco : Thanks for the link; the only thing is that macros are dependent from the stl libraries version, which I'd prefer to avoid. +1
    Bklyn : Its also a bit frustrating that commands like "plist foo std::string" give syntax errors. It appears that the value_type can't contain any punctuation.
    jpalecek : I haven't tried, but if this works the same as the rest of GDB, enclosing the name with punctuated name in single quotes should do it.
  • Try De-Referencing STL Containers: on this page: http://www.yolinux.com/TUTORIALS/GDB-Commands.html

    Richard Corden : These look to be the business!
    Paolo Tedesco : They're actually the same macros as in the previous answer :) I'm afraid there's no simpler solution.
  • There's always the obvious: Define your own test-function... Call it from gdb. E.g.:

    #define SHOW(X) cout << # X " = " << (X) << endl
    
    void testPrint( map<int,int> & m, int i )
    {
      SHOW( m[i] );
      SHOW( m.find(i)->first );
    }
    
    int
    main()
    {
        std::map<int,int> m;
        m[1] = 2;
        m[2] = 4;
        return 0;  // Line 15.
    }
    

    And:

    ....
    Breakpoint 1 at 0x400e08: file foo.C, line 15.
    (gdb) run
    Starting program: /tmp/z/qD 
    
    Breakpoint 1, main () at qD.C:15
    (gdb) call testPrint( m, 2)
    m[i] = 4
    (*m.find(i)).first = 2
    (gdb)
    
    sean riley : as long as the process is running. not so useful for core-dumps.
  • The stl-views.gdb used to be the best answer there was, but not anymore.

    This isn't integrated into the mainline GDB yet, but here is what you get using the 'archer-tromey-python' branch:

    (gdb) list
    1   #include <map>
    2   int main(){
    3       std::map<int,int> m;
    4       m[1] = 2;
    5       m[2] = 4;
    6       return 0;
    7   }
    (gdb) break 6
    Breakpoint 1 at 0x8048274: file map.cc, line 6.
    (gdb) run
    
    Breakpoint 1, main () at map.cc:6
    6       return 0;
    (gdb) print m
    $1 = std::map with 2 elements = {
      [1] = 2,
      [2] = 4
    }
    (gdb) quit
    

0 comments:

Post a Comment