29
double var1, var2;
std::vector<double *> x;

var1 = 1;
var2 = 2;

x.push_back(&var1);
x.push_back(&var2);

When I debug this code in gdb and try print x[0] or *x[0] I get:

Could not find operator[].

Now if I include this line after the push_back:

x[0] = &var1;

I can access any specific elements in gdb. The same thing happens with other members such as front(), at(), etc. My understanding is that the compiler/linker includes only the member functions present in the source code and those are the ones I can use in gdb. Is there a way to include every member function of std::vector so I can access them in gdb?

JFMR
  • 23,265
  • 4
  • 52
  • 76
m3phi
  • 293
  • 1
  • 3
  • 6
  • 1
    Turn off optimizations? – Qix - MONICA WAS MISTREATED Jun 09 '14 at 22:44
  • 1
    I'm not sure of a way to prevent the compiler/linker from stripping the `[]` operator code from the executable, but have a look at this answer for a potential workaround: http://stackoverflow.com/questions/253099/how-do-i-print-the-elements-of-a-c-vector-in-gdb – slugonamission Jun 09 '14 at 22:44
  • @Qix I have only -g -Wall on – m3phi Jun 09 '14 at 22:51
  • 2
    Its not "stripped" because its never *added*. From what I recall (yes, its sketchy; a monday you know), that operator isn't virtual, and if there is no usage, neither will there be expansion of implementation for the given type. You can probably explicitly force it however, though I admittedly have never tried. – WhozCraig Jun 09 '14 at 22:51
  • Does this answer your question? [Forcing the compiler to generate code for all member functions of a template class?](https://stackoverflow.com/questions/21166762/forcing-the-compiler-to-generate-code-for-all-member-functions-of-a-template-cla) {note that there are some answers in each question that is not included in the other.} – user202729 Feb 17 '20 at 08:19

4 Answers4

41

My understanding is that the compiler/linker includes only the member functions present in the source code and those are the ones I can use in gdb.

Your understanding is incorrect / incomplete.

std::vector is a template class. Without explicit instantiation, the compiler is required to instantiate only the methods called (usually a subset of methods present in the source).

Is there a way to include every member function of std::vector so I can access them in gdb?

For a given type T, you should be able to explicitly instantiate entire vector for that T, by requesting it, e.g.:

template class std::vector<double>;
Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • +1 and I had no idea explicit instantiation fully instantiated the works. Never really thought about it till you mentioned it. Now that I think about it more, it makes total sense. Thanks for teaching me something today!. – WhozCraig Jun 10 '14 at 03:28
  • 1
    Why the explicit instantiation must be put outside of the main function? – duleshi Jun 12 '14 at 06:26
  • 2
    @duleshi the explicit instantiation process generates a recognizable class, which is comparable to defining a class. If you can't define a class in main, I don't see why you should be allowed to do explicit instantiation in main. – h9uest Mar 31 '15 at 09:04
  • I used this and it worked, so thanks!! But I don't understand why I had to do it, because in my code I do use `operator[]` of the template class (which is `boost::interprocess::offset_ptr`, btw) so I would guess it would have to be instantiated anyway. And I'm _not_ using optimizations. – joao Apr 12 '19 at 10:52
  • Just a comment. On Ubuntu 16 LTS these explicit instantiations are unnecessary, but on the Mac they **are**. I can't say I tried to turn off all possible compiler optimizations (I just complied with no extra tricks like O1, O2, or O3). @Employed Russian helped me end my three hours of painful trial and error. – MegaNightdude Aug 21 '20 at 04:25
18

Try print by inner member of the vector.

print *(x._M_impl._M_start+0)

Here 0 is the index of data you want to inspect.

Inspired from this answer.

phil
  • 2,558
  • 1
  • 19
  • 23
3

Alternately, you coud use the GDB extension below, which will poke at the std::vector fields of GNU libstdc++ and thus works regardless of whether operator[] is instantiated.

Load with:

(gdb) guile (load "the-file.scm")

This creates a new vref command:

(gdb) vref my_vector 0

Code (requires GDB built with Guile support):

(use-modules (gdb)
             (ice-9 match))

(define (std::vector-ref vector index)
  (let* ((impl  (value-field vector "_M_impl"))
         (start (value-field impl "_M_start")))
    (value-subscript start index)))

(define %vector-ref-command
  (make-command "vref"
                #:command-class COMMAND_OBSCURE
                #:doc "Access an element of an std::vector."
                #:invoke
                (lambda (self args tty?)
                  (match (string-tokenize args)
                    ((variable index)
                     (let* ((value (std::vector-ref (parse-and-eval variable)
                                                   (string->number index)))
                            (index (history-append! value)))
                       (format #t "$~a = ~a~%"
                               index (value-print value)))))
                  #t)))

(register-command! %vector-ref-command)
civodul
  • 31
  • 1
-1

The .at(), .begin() functions work for me for some reason. Could be cause I have the -g flag set.

Ivankovich
  • 119
  • 2
  • 8