This answer is based on a comment by bcumming in How do I print the elements of a C++ vector in GDB? and was tested with Codelite 10.0.0, gcc 4.9.2 and gdb 7.7.1 on 64 bit Debian 8. That question concerned displaying all the elements of the vector. The answer by John Carter had the disadvantage of involving internal library-dependent pointer names and the advantage that it works fine even if the inferior (the program being debugged) did not have compiled into it the code for operator [ ]. (See: gdb Could not find operator[].)
If I want to see 4
elements of vector vecV
p starting with index [3]
then the gdb print command is:
p *(&vecV[3]) @ 4
This is my answer. I have been trying to figure out how to do this for years, and it is not in the gdb manual, as far as I know. The text below concerns variations of and the principles behind this technique.
One reason for doing this is to reduce the clutter of displaying all the elements of a vector. The other is to reduce the time it takes gdb to respond for the Watch window lines, such as for each "step over" IDE operation. I find that gdb, with its Python-based STL pretty printing mechanisms, can take seconds or tens of seconds to respond to large numbers of simple elements, or few more complex ones.
This is an application to vectors of the technique described in gdb manual section 10.4 Artificial Arrays where the binary operator @
works fine with C-style arrays: p arrA[3] @ 4
but not vectors and the like from the containers library (STL).
The above use of @
, starting with a particular vector element, works fine in Codelite's Watch window, where the p
part above is not needed. The single line which Codelite displays can be opened up by clicking right-pointing arrows to show all the values of the elements and the objects, vectors of strings etc. that they contain. However, it does not work as the basis for displaying just just one inner element, such as some class object, an int or a string, of each of the range of vector elements. To do this, four Watch lines must be created (add p
for driving gdb directly):
vec[3].log
vec[4].log
vec[5].log
vec[6].log
This of course is tedious. The solution is to add some variables to the inferior which are only to be used by gdb. These can be static, outside any function and so "global":
static int XX = 0;
static int YY = 0;
static int ZZ = 0;
Their values can be set from within Codelite, while the inferior is paused at a breakpoint, by commands such as set XX = 3
entered into the "Send" bar at the bottom of the gdb console, which is under the "(red ladybug icon) Output" tab of the "Debugger" window. This enables me to use four Watch lines, each focused on just the "log" member of the four chosen elements in the vector, which can be easily steered to any part of the vector by altering the value of XX
:
vecV[XX + 0].log
vecV[XX + 1].log
vecV[XX + 2].log
vecV[XX + 3].log
What's more, in my experience, changing XX
causes Codelite to not only display the new data, but to highlight in red any which is different from what it displayed with the previous value of XX
.
If log
was an object containing a string which was too long to view in the Watch window (Settings > GDB Settings > GNU gdb debugger > General > Display > Number of elements to display for arrays/strings), then I can use the above scheme and substr()
with some other gdb-set variables to control which range of the strings are displayed:
vecV[XX + 0].log.strS.substr(AA, BB)
vecV[XX + 1].log.strS.substr(AA, BB)
vecV[XX + 2].log.strS.substr(AA, BB)
vecV[XX + 3].log.strS.substr(AA, BB)
Such variables can be applied to the main technique to provide a steerable, resizable, window of display into a vector, by typing one or two commands to the gdb console, rather than editing the Watch window line, which typically involves lots of mouse/trackball clicking to re-open all the branches of the objects which are of interest:
(&vecV[YY]) @ ZZ