我将 gdb 与 -x 参数一起使用,以便进行调试而不必在每个断点处以交互方式继续。
[root@StackOverflow.com] $ cat gdb_cmds_01
b SomeSourceFile.cpp:123
commands
bt
cont
end
然后我附加到一个在执行过程中使用 SomeSourceFile.cpp 的进程:
[root@StackOverflow.com] $ gdb -p 'pidof SomeRunningProgram' -x gdb_cmds_01
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
...
<GDB outputs a set S of backtraces as instructed by gdb_cmds_01>
现在,让 SomeSourceFile.cpp:123 包含如下一行:
if (foo(person, &place, *time) == "Alice") { ... <do stuff > ... }
然后假设我只想在 foo(...)
的返回值不等于“Alice”时中断 SomeSourceFile:123。
基于: How to inspect the return value of a function in GDB? ,我知道 gdb 可以检查函数的返回值。
和https://sourceware.org/gdb/onlinedocs/gdb/Break-Commands.html告诉我可以非交互地检查变量的值:
<...>
For example, here is how you could use breakpoint commands to print the value of x at entry to foo whenever x is positive.
break foo if x>0
commands
silent
printf "x is %d\n",x
cont
end
<...>
我试过类似的东西:
[root@StackOverflow.com] $ cat gdb_cmds_01
b SomeSourceFile.cpp:123 if foo(person, &place, *time) != "Alice"
commands
bt
cont
end
但是 GDB 吐出:
gdb_cmds_01:1: Error in sourced command file:
No symbol "place" in current context.
这可以解决吗?
为了仅在 foo(...) != "Alice"
时在 SomeSourceFile.cpp:123 上中断,我是否也可以非交互地检查函数的返回值?
换句话说,我只想看到回溯集合 S 的一个子集 R,这样对于 R 中的所有回溯 b,foo(...)
的返回总是不等于“爱丽丝”。
最佳答案
Suppose I want to break on SomeSourceFile:123 only if the return of foo(...) is not equal to "Alice".
如果您转到较低的(汇编级别)并且代码是在没有优化的情况下构建的,那么这很容易做到。
如果您可以像这样修改源代码,这也是微不足道的:
if (foo(...) == "Alice") { ...
} else {
int x = 0; if (x) abort(); // break here
}
现在您只需在第 125 行设置断点即可。
那么如何在不修改源代码的情况下做到这一点呢?
你必须明白,编译器调用了一些bool operator==()
,比较返回值是true
还是false
,并有条件地跳转当条件为假时,围绕 if
的主体。
(gdb) 信息行 123
将为您提供为此源代码行生成的指令范围。
反汇编该范围的指令将允许您找到对 operator==
的调用,并向您展示比较 EAX
的指令(JE
或 JNE
) 与 0
或 1
。
然后您可以在条件跳转指令上设置断点,并使用 $EAX
(或 $RAX
用于 64 位代码)作为该断点的条件。
关于c++ - 仅当函数的返回值等于 "Value"时,gdb 才能有条件地非交互地中断函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51069577/