6

For example, with:

#include <functional>
#include <iostream>

int myfunc(int i){ return i + 1; }

int main() {
    std::function<int(int)> f = myfunc;
    int i = f(1);
    std::cout << i << std::endl;
}

compiled with:

g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp

if I try to do a step into the call f(1), then it first leads me in to C++ standard library code, and I either have to think really hard and do the right next/step sequence, or be dumb and hit step 17 times before reaching the actual myfunc call.

Is there an easier way to go about this, maybe with some existing GDB/Python script?

This was basically done by Microsoft people for Visual Studio as mentioned at: https://devblogs.microsoft.com/cppblog/improving-the-debugging-experience-for-stdfunction/

I like it that is is possible to step into the stdlibc++ by default in Ubuntu and have already used it before, but it would be awesome if GDB could step into std::function user code by default, and have some other mechanism to go into libstdc++ for this specific case.

I'm tempted to go a bit cheeky and just use the following Python GDB script that repeats a command n times: gdb - perform a command n times which allows me to do:

repeat-cmd 17 s

Related: QtCreator debugger: step into std::function

Tested in Ubuntu 18.04, GDB 8.1, GCC 7.4.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985

2 Answers2

4

The first thing which will not work in your use case is

gdb skip -gfile bits/*.h

As you already mentioned, this will skip also over your code which was called from within the std library.

Next idea: Skipping over functions with "known name". As we have typically std:: in front of the function name a used the following .gdbinit. It looks much better:

sys.path.insert(0, '/usr/share/gcc-9/python/')
from libstdcxx.v6.printers import register_libstdcxx_printers
register_libstdcxx_printers (None)

import gdb
import re

def stop_handler(event):
    frame_name = gdb.selected_frame().name();
    if re.search("(operator new.*)|(^__gnu_cxx::.*)|(^std::.*)", frame_name) != None:
        gdb.execute("step")

gdb.events.stop.connect(stop_handler)
end

I searched now a while to find something to get the current file/line-number combination into python but did not find anything. Is there any python access to the current file name and line number? If so, this will be much simpler in this case. Would be nice if someone can add some info's here!

Remark: in ddd that will work not very well, as an internal step from python will not be recognized by the gui. So the green arrow stays on the last stepped line and not the current one. If someone knows also a trick in such a case, any help is welcome!

UPDATE:

If you use the following as .gdbinit

python
import sys
sys.path.insert(0, '/usr/share/gcc-9/python/')
from libstdcxx.v6.printers import register_libstdcxx_printers
register_libstdcxx_printers (None)

import gdb
import re

def stop_handler(event):
    sal = gdb.selected_frame().find_sal()
    if sal == None:
        gdb.execute("step")
    else:
        symtab = sal.symtab;
        if symtab == None:
            gdb.execute("step")
        else:
            file_name = symtab.fullname();
            if re.search("(.*bits.*)", file_name ) != None:
                gdb.execute("step")

gdb.events.stop.connect(stop_handler)
end

Everything works perfectly on my pc. As an additional hint: If using ddd, you can open the backtrace window and then the green arrow will follow also the python internal gdb steps. That works perfectly for me! Thanks for the question! :-)

Maybe the regexp can be updated to fit for filtering more external libs or to be more selective.

Klaus
  • 24,205
  • 7
  • 58
  • 113
  • Thanks for this suggestion Klaus. You can get the current line and file name from the GDB Python API as shown at: https://github.com/cirosantilli/cpp-cheat/blob/b4aaea05a02f5953a484aefde4c34216ddec9574/gdb/print_lines.py#L19 BTW – Ciro Santilli OurBigBook.com Dec 23 '19 at 11:33
  • 1
    @CiroSantilli新疆改造中心法轮功六四事件: I did an update, take a look :-) For me this one works really perfect also with ddd if the backtrae window is open. Thanks for the question! I had the "problem" for years but getting your question i solved it now also for me! :-) – Klaus Dec 23 '19 at 12:14
1

Just put break on the line source.cpp: 5

(gdb) b source.cpp:5

and press r(run)

ore before step to f(1) set

s 25

this will lead to the entry into the function

#include <functional>
#include <iostream>

int myfunc(int i) { 
    return i + 1;
}

int main() {
    std::function<int(int)> f = myfunc;
    int i = f(1);
    std::cout << i << std::endl;
}
Oh-Ben-Ben
  • 163
  • 2
  • 7
  • 2
    This is generally not acceptable because the `std::function` normally used when there are multiple possible functions that get called based on runtime behavior, so you can't easily know which will will get called. – Ciro Santilli OurBigBook.com Dec 20 '19 at 22:04