例如,与:
#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 中测试。
不起作用的第一件事是
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 步骤。这对我来说非常有效!谢谢你的提问! :-)
也许可以更新正则表达式以适应过滤更多外部库或更具选择性。
(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;
}
我想出了另一个对我有用的脚本。
(我是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