C++ 只有当调用堆栈中存在某个方法时,才可能在断点上中断吗?
假设我有一个方法C++ 只有当调用堆栈中存在某个方法时,才可能在断点上中断吗?,c++,debugging,gdb,lldb,C++,Debugging,Gdb,Lldb,假设我有一个方法foo,在遍历对象的层次结构时,它被不同的方法调用 只有当方法bar调用方法foo时,才可能在方法foo内部中断(因此bar存在于调用堆栈中) LLDB或GDB支持这样的用例吗?在GDB中,您可以将调试器与断点相关联,因此为了实现您的目标,您可以在bar()中放置一个断点,在那里调用foo(),并使用命令列表在foo()中设置断点,然后继续。调用foo()后,需要在bar()中的另一个断点来清除foo()中的断点 因此: 当然,如果这种情况很少发生,您可以手动设置断点 如果未直接
foo
,在遍历对象的层次结构时,它被不同的方法调用
只有当方法bar
调用方法foo
时,才可能在方法foo
内部中断(因此bar
存在于调用堆栈中)
LLDB或GDB支持这样的用例吗?在GDB中,您可以将调试器与断点相关联,因此为了实现您的目标,您可以在
bar()
中放置一个断点,在那里调用foo()
,并使用命令列表在foo()
中设置断点,然后继续。调用foo()
后,需要在bar()
中的另一个断点来清除foo()
中的断点
因此:
当然,如果这种情况很少发生,您可以手动设置断点
如果未直接从bar()
调用foo()
,或者可能从bar()
中的多个位置调用foo()
,则相同的解决方案适用;如果bar()
,在开始时设置断点并在结束时清除它就足够了
一个警告;如果应用程序是多线程的,并且可以从多个线程调用
bar()
或foo()
,那么您将需要一个。看看$\u caller\u是和朋友。(FWIW正是这个用例促使我致力于将Python添加到gdb…)
一个简单的用法是:
(gdb) break foo if $_any_caller_matches("bar")
在lldb中执行此操作的方法是编写一个基于Python的断点命令,该命令检查命中断点的线程堆栈,如果它不包含带有该函数的帧,则继续执行。断点命令通过分别从函数返回True或False来通知lldb停止或不停止。因此,一种非常简单的方法是创建一个Python文件(break_here.py):
假设该文件位于/tmp中。然后在lldb中,您可以执行以下操作:
(lldb) com scr imp /tmp/break_here.py
(lldb) br s -n whatever
(lldb) br com add --python-function break_here.break_here
为什么不把断点放在bar()
调用foo()
?@YSC我经常遇到bar
和foo
之间的堆栈很深的情况。我的意思是,bar
调用a
哪个调用b
哪个调用c
哪个。。。最终调用foo
@Angew我明白了。也许OP应该编辑它的问题,让我们知道他是否在这种情况下。@YSC:这是标题和第一段所暗示的,但第二段明确指出,foo是从bar调用的,但这可能是无意中暗示的。无论哪种方式,都适用相同的解决方案。@YSC:也可能是它不是foo()
上的一个简单断点,而是foo()
中某个有条件执行的断点。这看起来是一个很好的解决方法,可以实现此结果,但是@Tom Tromey的回答似乎提供了一个更为开发人员友好的解决方案。@Placinta:我同意,我不是gdb专家。我建议的方法是我在其他调试器中使用过的方法,并且可能更具可移植性。这看起来正是我想要的,谢谢!唯一的问题是为lldb找到一个类似的构造,而lldb似乎不支持这种构造。
import lldb
desired_func = "some_func"
def break_here(frame, bp_loc, dict):
thread = frame.thread
for frame in thread.frames:
if frame.name == desired_func:
return True
return False
(lldb) com scr imp /tmp/break_here.py
(lldb) br s -n whatever
(lldb) br com add --python-function break_here.break_here