我正在通过gdb运行一个应用程序,我想在访问/更改特定变量时设置一个断点。有什么好的方法吗?我也对监视C/ c++中的变量的其他方法感兴趣,以查看它是否/何时发生变化。
当前回答
除了已经被asksol和Paolo M
我一开始没看明白,为什么要投结果。虽然我读过这个:https://sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints.html,但这对我来说并不直观。
所以我做了一个实验,让结果更清楚: 代码:(假设int main()在第3行;int i=0在第5行和其他代码..从10号线开出。
int main()
{
int i = 0;
int j;
i = 3840 // binary 1100 0000 0000 to take into account endianness
other code..
}
然后我用可执行文件启动GDB 在我的第一次尝试中,我在没有强制转换的变量位置上设置了断点,以下是显示的结果
Thread 1 "testing2" h
Breakpoint 2 at 0x10040109b: file testing2.c, line 10.
(gdb) s
7 i = 3840;
(gdb) p i
$1 = 0
(gdb) p &i
$2 = (int *) 0xffffcbfc
(gdb) watch *0xffffcbfc
Hardware watchpoint 3: *0xffffcbfc
(gdb) s
[New Thread 13168.0xa74]
Thread 1 "testing2" hit Breakpoint 2, main () at testing2.c:10
10 b = a;
(gdb) p i
$3 = 3840
(gdb) p *0xffffcbfc
$4 = 3840
(gdb) p/t *0xffffcbfc
$5 = 111100000000
正如我们可以看到的,断点被击中了第10行,这是我设置的。GDB没有崩溃,因为虽然变量I发生了变化,但被监视的位置没有改变(由于字节顺序,因为它仍然保持全部为0)
在第二次尝试中,我对变量的地址进行了强制转换,以观察所有的sizeof(int)字节。这一次:
(gdb) p &i
$6 = (int *) 0xffffcbfc
(gdb) p i
$7 = 0
(gdb) watch *(int *) 0xffffcbfc
Hardware watchpoint 6: *(int *) 0xffffcbfc
(gdb) b 10
Breakpoint 7 at 0x10040109b: file testing2.c, line 10.
(gdb) i b
Num Type Disp Enb Address What
6 hw watchpoint keep y *(int *) 0xffffcbfc
7 breakpoint keep y 0x000000010040109b in main at testing2.c:10
(gdb) n
[New Thread 21508.0x3c30]
Thread 1 "testing2" hit Hardware watchpoint 6: *(int *) 0xffffcbfc
Old value = 0
New value = 3840
Thread 1 "testing2" hit Breakpoint 7, main () at testing2.c:10
10 b = a;
GDB中断,因为它检测到值已经改变。
其他回答
Watch只在写时中断,rwatch可以在读时中断,而awatch可以在读/写时中断。
你可以在内存位置上设置读观察点:
gdb$ rwatch *0xfeedface
Hardware read watchpoint 2: *0xfeedface
但是rwatch和awatch命令有一个限制;不能使用GDB变量 在表达式:
gdb$ rwatch $ebx+0xec1a04f
Expression cannot be implemented with read/access watchpoint.
所以你必须自己扩展它们:
gdb$ print $ebx
$13 = 0x135700
gdb$ rwatch *0x135700+0xec1a04f
Hardware read watchpoint 3: *0x135700 + 0xec1a04f
gdb$ c
Hardware read watchpoint 3: *0x135700 + 0xec1a04f
Value = 0xec34daf
0x9527d6e7 in objc_msgSend ()
编辑:哦,顺便说一下。您需要硬件或软件支持。软件显然要慢得多。要了解您的操作系统是否支持硬件观察点,可以查看can-use-hw-watchpoints环境设置。
gdb$ show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.
假设第一个答案引用的是类c语法(char *)(0x135700 +0xec1a04f),那么执行rwatch *0x135700+0xec1a04f的答案是不正确的。正确的语法是rwatch *(0x135700+0xec1a04f)。
由于缺少(),我在自己尝试使用观察点时感到非常痛苦。
除了已经被asksol和Paolo M
我一开始没看明白,为什么要投结果。虽然我读过这个:https://sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints.html,但这对我来说并不直观。
所以我做了一个实验,让结果更清楚: 代码:(假设int main()在第3行;int i=0在第5行和其他代码..从10号线开出。
int main()
{
int i = 0;
int j;
i = 3840 // binary 1100 0000 0000 to take into account endianness
other code..
}
然后我用可执行文件启动GDB 在我的第一次尝试中,我在没有强制转换的变量位置上设置了断点,以下是显示的结果
Thread 1 "testing2" h
Breakpoint 2 at 0x10040109b: file testing2.c, line 10.
(gdb) s
7 i = 3840;
(gdb) p i
$1 = 0
(gdb) p &i
$2 = (int *) 0xffffcbfc
(gdb) watch *0xffffcbfc
Hardware watchpoint 3: *0xffffcbfc
(gdb) s
[New Thread 13168.0xa74]
Thread 1 "testing2" hit Breakpoint 2, main () at testing2.c:10
10 b = a;
(gdb) p i
$3 = 3840
(gdb) p *0xffffcbfc
$4 = 3840
(gdb) p/t *0xffffcbfc
$5 = 111100000000
正如我们可以看到的,断点被击中了第10行,这是我设置的。GDB没有崩溃,因为虽然变量I发生了变化,但被监视的位置没有改变(由于字节顺序,因为它仍然保持全部为0)
在第二次尝试中,我对变量的地址进行了强制转换,以观察所有的sizeof(int)字节。这一次:
(gdb) p &i
$6 = (int *) 0xffffcbfc
(gdb) p i
$7 = 0
(gdb) watch *(int *) 0xffffcbfc
Hardware watchpoint 6: *(int *) 0xffffcbfc
(gdb) b 10
Breakpoint 7 at 0x10040109b: file testing2.c, line 10.
(gdb) i b
Num Type Disp Enb Address What
6 hw watchpoint keep y *(int *) 0xffffcbfc
7 breakpoint keep y 0x000000010040109b in main at testing2.c:10
(gdb) n
[New Thread 21508.0x3c30]
Thread 1 "testing2" hit Hardware watchpoint 6: *(int *) 0xffffcbfc
Old value = 0
New value = 3840
Thread 1 "testing2" hit Breakpoint 7, main () at testing2.c:10
10 b = a;
GDB中断,因为它检测到值已经改变。
我尝试了以下方法:
$ cat gdbtest.c
int abc = 43;
int main()
{
abc = 10;
}
$ gcc -g -o gdbtest gdbtest.c
$ gdb gdbtest
...
(gdb) watch abc
Hardware watchpoint 1: abc
(gdb) r
Starting program: /home/mweerden/gdbtest
...
Old value = 43
New value = 10
main () at gdbtest.c:6
6 }
(gdb) quit
因此,这似乎是可能的,但您似乎确实需要一些硬件支持。
你要找的是观察点。
使用
(gdb) watch foo:观察变量foo的值
(gdb) watch *(int*)0x12345678:监视由地址指向的值,转换为您想要的任何类型
(gdb) watch a*b + c/d:查看任意复杂的表达式,在程序的母语中有效
观察点有三种:
注意:当发生写操作时,GDB将中断 Rwatch:当读取发生时,GDB将中断 注意:GDB在这两种情况下都会崩溃
您可以根据自己的需要选择更合适的。
要了解更多信息,请查看这个。
推荐文章
- Visual Studio:如何打破处理异常?
- 在C和c++中静态变量存储在哪里?
- 确保您的项目构建设置正在生成一个dSYM文件。对于所有配置,DEBUG_INFORMATION_FORMAT都应该设置为dwarf-with-dsym
- 如何获得GDB中所有线程的回溯?
- 为什么标准迭代器范围是[begin, end]而不是[begin, end]?
- c++双地址操作符?(& &)
- 函数标题中的箭头操作符(->)
- 如何在c++中初始化一个向量
- 返回类型为'?:'(三元条件运算符)
- 当分配vector时,它们使用的是堆上的内存还是堆栈上的内存?
- 互斥实例/教程?
- 如何添加一个'或'条件在#ifdef
- 纯虚函数的实现
- 为什么在c++中声明enum时使用typedef ?
- 对静态类成员的未定义引用