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