R@M3$H.NBlog

Print the elements of a C++ vector in GDB?

26 April, 2013 - 3 min read

With GCC 4.1.2, to print the whole of a std::vector<int> called myVector, do the following:

print *(myVector._M_impl._M_start)@myVector.size()

To print only the first N elements, do:

print *(myVector._M_impl._M_start)@N

Explanation

This is probably heavily dependent on your compiler version, but for GCC 4.1.2, the pointer to the internal array is:

myVector._M_impl._M_start 

And the GDB command to print N elements of an array starting at pointer P is:

print P@N

Or, in a short form (for a standard .gdbinit):

p P@N

(gdb) what vIPIFMOC
type = std::vector<SManagedObj,std::allocator<SManagedObj> >
(gdb) p vIPIFMOC
$2 = {
<std::_Vector_base<SManagedObj,std::allocator<SManagedObj> >> = {
_M_impl = {
<std::allocator<SManagedObj>> = {
<__gnu_cxx::new_allocator<SManagedObj>> = {<No data fields>}, <No data fields>},
members of std::_Vector_base<SManagedObj,std::allocator<SManagedObj> >::_Vector_impl:
_M_start = 0x556802cb70,
_M_finish = 0x556802cc30,
_M_end_of_storage = 0x556802cc30
}
}, <No data fields>}
(gdb) p *(vIPIFMOC._M_impl._M_start)@1

Options-2:

In the gdb:

source {full_path}stl-views.gdb

now you'll have new commands, such as pvector, plist, pmap and more (replace {full_path} with the full path to the file.

You can also put the command source stl-views.gdb in ~/.gdbinit - and then you'll have it automatically every time you launch gdb.

stl-views.gdb

Option-3:

For performance reasons, SGI's STL implmentation is all inline; a naming convention is generally followed (i.e. double underscore as a prefix for local variables), but tends to create long, cryptic variable names. Unfortunately, raw gdb is not a graceful way to debug STL-heavy code, the reasons being -

  • First, the 'T' in "STL" stands for "template"; while you as a programmer have full information about what is the argument to the template, gdb does not necessarily have access to this knowledge. As a result, gdb will tend to think that every (templated) pointer is a (void*), and will have no access to its internals should it point to a class.
  • The traversal of some containers (hashes, trees) is complicated; obtaining the "first()" and "next()" elements of a container is a tricky task.
  • Some data, such as the size of lists, is not stored explicitly - and there is simply no way to find it out in gdb.

gdb_stl_utils.gdb  is a small utility that may help solving these problems.
To use it, download and compile StlStdContainers.cc (a simple g++ StlStdContainers.cc -o StlStdContainers.o will do); then, load gdb_stl_utils into gdb by using the command "source gdb_stl_utils" (in gdb) or including in .gdbinit. You will then have access to the following gdb function:

p_stl_vector, p_stl_vector_size
p_stl_list, p_stl_list_size
p_stl_tree, p_stl_tree_size (for maps and sets)
p_stl_hash, p_stl_hash_size (for hash_maps and sets)

The names are self-explanatory: the functions print the contents and the sizes of STL containers given to them.

Good luck and happy debugging!

Note: From above attachments, remove .doc extensions and use.