为什么 gdb watch 命令跟踪不到 glibc 库函数修改的变量?

baozhb 2013-09-15 10:09:18
在代码中有两个变量,局部变量 a 和全局变量 ch。
安排一段代码修改变量 a,可以用 watch 跟踪到变量改变,
但了用 glibc 中的 read() 函数修改变量 ch,用 watch 命令却跟踪不到变化

代码如下

14 const char *const filename = "./A-small-practice.in";
15
16 void change_a(int *num)
17 {
18 *num = 8;
19 }
20
21 char ch;
22
23 int main()
24 {
25 int fd;
26 int a;
27 a = 12;
28 a = 10;
29 a = 9;
30
31 change_a(&a);
32 a = 7;
33
34 fd = open(filename, O_RDONLY);
35
36 read(fd, &ch, 1); /* 1 */
37 printf ("%c\n", ch);
38
39 read(fd, &ch, 1); /* 0 */
40 printf ("%c\n", ch);
41
42 read(fd, &ch, 1); /* \n */
43 printf ("%c\n", ch);
44
45 read(fd, &ch, 1); /* 1 */
46 printf ("%c\n", ch);
47
48 read(fd, &ch, 1); /* 0 */
49 printf ("%c\n", ch);
50
51 printf ("\n");
52 close (fd);
53
54 return 0;
55 }

用 gdb watch 跟踪变量 a,变量 ch的变化:
rockbao@rockbao-desktop:~/Practice$ gdb ./foo
GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/rockbao/Practice/foo...done.
(gdb) break main
Breakpoint 1 at 0x80484bb: file foo.c, line 27.
(gdb) r
Starting program: /home/rockbao/Practice/foo

Breakpoint 1, main () at foo.c:27
27 a = 12;
(gdb) watch a
Hardware watchpoint 2: a
(gdb) watch ch
Hardware watchpoint 3: ch
(gdb) c
Continuing.
Hardware watchpoint 2: a

Old value = 134514249
New value = 10

main () at foo.c:29
29 a = 9;
(gdb) c
Continuing.
Hardware watchpoint 2: a

Old value = 10
New value = 9

main () at foo.c:31
31 change_a(&a);
(gdb) c
Continuing.
Hardware watchpoint 2: a

Old value = 9
New value = 8

change_a (num=0xbffff108) at foo.c:19
19 }
(gdb) c
Continuing.
Hardware watchpoint 2: a

Old value = 8
New value = 7

main () at foo.c:34
34 fd = open(filename, O_RDONLY);
(gdb) c
Continuing.
1
0


1
0



Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
0x0014a113 in __libc_start_main () from /lib/i386-linux-gnu/libc.so.6
(gdb) c
Continuing.
[Inferior 1 (process 2524) exited normally]
(gdb)

其中红色表示变量 a 的变化得到了跟踪,
但为什么变量 ch 的变化得不到跟踪呢?何况变量 ch 是全局作用域的(如果可以跟踪到,应该出现在绿色标识的区域)。
谢谢回答!
...全文
390 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
zodiac1111 2013-09-24
  • 打赏
  • 举报
回复
http://stackoverflow.com/questions/18974012/gdb-watch-can-not-variable-modified-by-glibcread-function
引用 楼主 baozhb 的回复:
在代码中有两个变量,局部变量 a 和全局变量 ch。 安排一段代码修改变量 a,可以用 watch 跟踪到变量改变, 但了用 glibc 中的 read() 函数修改变量 ch,用 watch 命令却跟踪不到变化 代码如下

 14 const char *const filename = "./A-small-practice.in";
 15 
 16 void change_a(int *num)
 17 {
 18     *num = 8;
 19 }
 20 
 21 char ch;
 22 
 23 int main()
 24 {
 25     int fd;
 26     int a;
 27     a = 12;
 28     a = 10;
 29     a = 9;
 30 
 31     change_a(&a);
 32     a = 7;
 33 
 34     fd = open(filename, O_RDONLY);
 35 
 36     read(fd, &ch, 1); /* 1 */
 37     printf ("%c\n", ch);
 38 
 39     read(fd, &ch, 1); /* 0 */
 40     printf ("%c\n", ch);
 41 
 42     read(fd, &ch, 1); /* \n */
 43     printf ("%c\n", ch);
 44 
 45     read(fd, &ch, 1); /* 1 */
 46     printf ("%c\n", ch);
 47 
 48     read(fd, &ch, 1); /* 0 */
 49     printf ("%c\n", ch);
 50 
 51     printf ("\n");
 52     close (fd);
 53
 54     return 0;
 55 }
用 gdb watch 跟踪变量 a,变量 ch的变化: rockbao@rockbao-desktop:~/Practice$ gdb ./foo GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08 Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i686-linux-gnu". For bug reporting instructions, please see: <http://bugs.launchpad.net/gdb-linaro/>... Reading symbols from /home/rockbao/Practice/foo...done. (gdb) break main Breakpoint 1 at 0x80484bb: file foo.c, line 27. (gdb) r Starting program: /home/rockbao/Practice/foo Breakpoint 1, main () at foo.c:27 27 a = 12; (gdb) watch a Hardware watchpoint 2: a (gdb) watch ch Hardware watchpoint 3: ch (gdb) c Continuing. Hardware watchpoint 2: a Old value = 134514249 New value = 10 main () at foo.c:29 29 a = 9; (gdb) c Continuing. Hardware watchpoint 2: a Old value = 10 New value = 9 main () at foo.c:31 31 change_a(&a); (gdb) c Continuing. Hardware watchpoint 2: a Old value = 9 New value = 8 change_a (num=0xbffff108) at foo.c:19 19 } (gdb) c Continuing. Hardware watchpoint 2: a Old value = 8 New value = 7 main () at foo.c:34 34 fd = open(filename, O_RDONLY); (gdb) c Continuing. 1 0 1 0 Watchpoint 2 deleted because the program has left the block in which its expression is valid. 0x0014a113 in __libc_start_main () from /lib/i386-linux-gnu/libc.so.6 (gdb) c Continuing. [Inferior 1 (process 2524) exited normally] (gdb) 其中红色表示变量 a 的变化得到了跟踪, 但为什么变量 ch 的变化得不到跟踪呢?何况变量 ch 是全局作用域的(如果可以跟踪到,应该出现在绿色标识的区域)。 谢谢回答!
zodiac1111 2013-09-16
  • 打赏
  • 举报
回复
不明白为什么会出现下面的现象,ch换成int类型貌似也不行(不会在read函数停下来). 如果可以务必说一下来源.如手册之类的 ch不被捕获:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
const char *const filename = "/etc/passwd";
int main(void)
{
	int fd;
	char ch;
	ch=1; // 这样的语句也是数据断点吧?
	fd = open(filename, O_RDONLY);
	read(fd, &ch, sizeof(char)); 
	printf ("%d\n", ch);
	close (fd);
	return 0;
}
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/zodiac1111/tmp/a.out...done.
(gdb) b main
Breakpoint 1 at 0x80484b5: file 1.c, line 11.
(gdb) r
Starting program: /home/zodiac1111/tmp/a.out 

Breakpoint 1, main () at 1.c:11
11		ch=1;
(gdb) wa ch
Hardware watchpoint 2: ch
(gdb) c
Continuing.
114

Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
ch被捕获:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
const char *const filename = "/etc/passwd";
int main(void)
{
	int fd;
	char ch;
	fd=1; //就增加这句
	ch=1;
	fd = open(filename, O_RDONLY);
	read(fd, &ch, sizeof(char)); 
	printf ("%d\n", ch);
	close (fd);
	return 0;
}
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/zodiac1111/tmp/a.out...done.
(gdb) b  main
Breakpoint 1 at 0x80484b5: file 1.c, line 11.
(gdb) r
Starting program: /home/zodiac1111/tmp/a.out 

Breakpoint 1, main () at 1.c:11
11		fd=1;
(gdb) wa ch
Hardware watchpoint 2: ch
(gdb) wa fd
Hardware watchpoint 3: fd
(gdb) c
Continuing.
Hardware watchpoint 2: ch

Old value = 8 '\b'
New value = 1 '\001'
main () at 1.c:13
13		fd = open(filename, O_RDONLY);
(gdb) c
Continuing.
Hardware watchpoint 3: fd

Old value = -1208221708
New value = 7
main () at 1.c:14
14		read(fd, &ch, sizeof(char)); 
(gdb) c
Continuing.
114

Watchpoint 2 deleted because the program has left the block in
which its expression is valid.

Watchpoint 3 deleted because the program has left the block in
which its expression is valid.
引用 1 楼 zhaolei_cpp 的回复:
数据断点必须硬件支持。 目前绝大多数cpu支持的都是32位的。 ch八位,硬件不支持,所以不行。 如果用vc的话,数据断点不是32位,会有提示。 不知道gdb为什么不提示,可能是bug。 没办法..............
zodiac1111 2013-09-16
  • 打赏
  • 举报
回复
引用 4 楼 baozhb 的回复:
[quote=引用 1 楼 zhaolei_cpp 的回复:] 数据断点必须硬件支持。 目前绝大多数cpu支持的都是32位的。 ch八位,硬件不支持,所以不行。 如果用vc的话,数据断点不是32位,会有提示。 不知道gdb为什么不提示,可能是bug。 没办法..............
但为什么我先把 ch 的地址转换成 int *,再用 ch 的地址来观察 ch 变化也是不行的。 假如 &ch = 0x804a028 我这样写 watch *(int *)0x804a028 也观察不到 ch 的变化,或者说 ch 处整型的变化。 [/quote] 我昨天也在网上查了很久,没找到答案,怀疑可能跟read函数有关,用libc-dbg库调调看.期待牛人给出解答呀.
baozhb 2013-09-16
  • 打赏
  • 举报
回复
引用 1 楼 zhaolei_cpp 的回复:
数据断点必须硬件支持。 目前绝大多数cpu支持的都是32位的。 ch八位,硬件不支持,所以不行。 如果用vc的话,数据断点不是32位,会有提示。 不知道gdb为什么不提示,可能是bug。 没办法..............
但为什么我先把 ch 的地址转换成 int *,再用 ch 的地址来观察 ch 变化也是不行的。 假如 &ch = 0x804a028 我这样写 watch *(int *)0x804a028 也观察不到 ch 的变化,或者说 ch 处整型的变化。
赵磊 2013-09-16
  • 打赏
  • 举报
回复
不过把gdb玩到如此深度,已经很厉害了。
赵磊 2013-09-16
  • 打赏
  • 举报
回复
数据断点必须硬件支持。 目前绝大多数cpu支持的都是32位的。 ch八位,硬件不支持,所以不行。 如果用vc的话,数据断点不是32位,会有提示。 不知道gdb为什么不提示,可能是bug。 没办法..............

18,777

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 专题技术讨论区
社区管理员
  • 专题技术讨论区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧