如何使用 GDB 从 C++ 函数单步调试到 std::function 用户代码?

问题描述 投票:0回答:3

例如,与:

#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;
}

编译为:

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

如果我尝试在调用中执行

step
f(1)
,那么它首先会引导我进入 C++ 标准库代码,我要么必须认真思考并执行正确的
next
/
step
顺序,或者愚蠢地在到达实际的
step
通话之前按
myfunc
17 次。

有没有更简单的方法来解决这个问题,也许使用一些现有的 GDB/Python 脚本?

这基本上是由 Microsoft 人员为 Visual Studio 完成的,如以下所述:https://devblogs.microsoft.com/cppblog/improving-the-debugging-experience-for-stdfunction/

我喜欢在 Ubuntu 中默认可以进入 stdlibc++ 并且之前已经使用过它,但是如果 GDB 可以默认进入 std::function

 用户代码,并且有一些其他机制来实现,那就太棒了对于这个特定情况,请进入 libstdc++。

我很想厚颜无耻地使用以下 Python GDB 脚本来重复命令 n 次:

gdb - 执行命令 n 次,这允许我这样做:

repeat-cmd 17 s

相关:

QtCreator 调试器:步入 std::function

在 Ubuntu 18.04、GDB 8.1、GCC 7.4 中测试。

c++ gdb
3个回答
4
投票
在您的用例中

不起作用的第一件事是

gdb 跳过 -gfile 位/*.h

正如您已经提到的,这也会跳过从 std 库中调用的代码。

下一个想法:跳过具有“已知名称”的函数。由于我们通常在函数名称前面有

std::

,所以使用了以下

.gdbinit
。看起来好多了:

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

我现在搜索了一段时间,想找到一些东西来将当前文件/行号组合输入Python,但没有找到任何东西。 python 有没有获取当前文件名和行号的方法?如果是这样,在这种情况下就会简单得多。如果有人可以在这里添加一些信息,那就太好了!

备注:在 ddd 中,这不会很好地工作,因为来自 python 的内部步骤不会被 gui 识别。因此,绿色箭头停留在最后一步的线上,而不是当前的线上。如果有人知道这种情况下的窍门,欢迎任何帮助!

更新:

如果您使用以下内容作为

.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

我的电脑上一切都运行良好。作为附加提示:如果使用 
ddd

,您可以打开回溯窗口,然后绿色箭头也会遵循 python 内部 gdb 步骤。这对我来说非常有效!谢谢你的提问! :-)


也许可以更新正则表达式以适应过滤更多外部库或更具选择性。


1
投票

(gdb) b source.cpp:5

然后按 r(运行)

在步骤 f(1) 之前设置

s 25

这将导致进入该函数

#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; }



0
投票

我想出了另一个对我有用的脚本。

(我是Python新手,如果您发现任何问题请随时纠正我)

python import gdb import threading import time class StopHandler(gdb.Command): def __init__(self): super(StopHandler, self).__init__("handle-stop", gdb.COMMAND_USER) gdb.events.stop.connect(self.on_stop) self.should_step = False def on_stop(self, event): frame = gdb.selected_frame() function_name = frame.name() if function_name and function_name.startswith("std::"): print(f"Program stopped at: {function_name}") self.should_step = True # Start a separate thread to run the step command delayed threading.Thread(target=self.delayed_step).start() else: print(f"Program stopped at: {function_name}") def delayed_step(self): time.sleep(0.1) # Wait 100ms, to be sure the stop-event is handled fully if self.should_step: self.should_step = False gdb.post_event(lambda: gdb.execute("step")) StopHandler() end

	
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.