Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gdb: how do you get the max value of a std::vector<float>?

Tags:

c++

vector

gdb

I am debugging some C++ code and I have a really large std::vector<floating_point_type> (float or double). In C++ code when I want the max value of the std::vector I can just use std::max_element(). So in gdb I tried to use the same code, but I got an error.

In gdb I used call std::max_element(x) and got an error message No symbol "max_element" in namespace "std".

Is there any way to get the max value of a vector in gdb?

I would also appreciate an explanation for why my attempt at using std::max_element was not working (perhaps std::max_element a header-only or inline function).

like image 782
Trevor Boyd Smith Avatar asked Jun 18 '18 13:06

Trevor Boyd Smith


People also ask

How do you find the maximum value of a vector?

You can use max_element to get the maximum value in vector. The max_element returns an iterator to largest value in the range, or last if the range is empty. As an iterator is like pointers (or you can say pointer is a form of iterator), you can use a * before it to get the value.

How do you find Max in C++?

The max() function in C++ accepts two values and returns the larger one. This function is available in <algorithm. h> . The max() function helps during coding contests when you want to find the maximum of two values in the logic.

What is p command in GDB?

The usual way to examine data in your program is with the print command (abbreviated p ), or its synonym inspect . It evaluates and prints the value of an expression of the language your program is written in (see section Using GDB with Different Languages).


2 Answers

std::max_element is a function template, not a function. You are asking GDB to do template argument deduction and the whole shebang involved with calling a template function without specifying arguments. It can't do that, naturally, it's not a full fledged compiler.

As far as I know any solution, from the simplest to the most complex, will require of you to modify your source in such a way that std::max_element is instantiated for the iterator types of your vector. So you may as well add "debug only" code that computes the maximum element and stores it into a local variable.

like image 137
StoryTeller - Unslander Monica Avatar answered Oct 18 '22 04:10

StoryTeller - Unslander Monica


(gdb) p std::max⭾⭾⭾

(No response from gdb)

 (gdb) p std::max_element(v.begin(), v.end())
 No symbol "max_element" in namespace "std".

Here is how to call an uninstantiated function template from gdb without breaking your session and recompiling your program.

  1. Open an editor and create a C++ source file with an explicit instantiation of the needed function. For example:

    // /tmp/tmpsource.cpp
    #include <algorithm>
    #include <vector>
    using T = std::vector<int>::iterator;
    template T std::max_element<T>(T, T);
    

    This can probably be automated somehow with a shell script. Give it a name of a function and template arguments, and it will generate you a complete buildable C++ source. Probably not worth the trouble though.

  2. Build a shared library/DLL from the source.

    g++ -fPIC -shared -ggdb -O0 -o /tmp/libtmpsource.so /tmp/tmpsource.cpp
    
  3. Load the library in your debugging session.

    load /tmp/libtmpsource.so
    # if this doesn't work
    p dlopen("/tmp/libtmpsource.so", 2)
    # or perhaps even
    p LoadLibraryA("c:/temp/libtmpsource.so")
    
  4. Let's try the function now.

    (gdb) p std::max_element(v.begin(), v.end())
    No symbol "max_element" in namespace "std".
    
  5. What? No worries, everything is under control. gdb is not a C++ compiler and it cannot do the template deduction thing. You need to specify your <...> yourself. Fortunately, autocompletion works (sometimes).

    (gdb) p std::max⭾
    (gdb) p std::max_element<__gnu_cxx::__normal_iterator<int*, std::vector<int, 
     std::allocator<int> > > >(__gnu_cxx::__normal_iterator<int*, std::vector<int, 
     std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, 
     std::allocator<int> > >)
    
like image 27
n. 1.8e9-where's-my-share m. Avatar answered Oct 18 '22 05:10

n. 1.8e9-where's-my-share m.