首页 > 代码库 > 《软件调试的艺术》笔记--检查和设置变量
《软件调试的艺术》笔记--检查和设置变量
1.使用print命令查看变量值
使用print命令(简写为p)可以查看变量值。
使用如下的程序1进行测试。
#include <stdio.h> struct node{ int index; struct node* next; }; int main(void) { struct node head; head.index = 1; head.next = NULL; int i; for(i=0; i<3; i++){ head.index++; } return 0; }(gdb) b main
Breakpoint 1 at 0x804839a: file a.c, line 10.
(gdb) r
Starting program: /root/a.out
Breakpoint 1, main () at a.c:10
10 head.index = 1;
(gdb) n
11 head.next = NULL;
(gdb)
14 for(i=0; i<3; i++){
(gdb)
15 head.index++;
(gdb)
14 for(i=0; i<3; i++){
(gdb) p head
$1 = {index = 2, next = 0x0}
(gdb) n
15 head.index++;
(gdb)
14 for(i=0; i<3; i++){
(gdb)
15 head.index++;
(gdb)
14 for(i=0; i<3; i++){
(gdb) p head
$3 = {index = 4, next = 0x0}
print命令允许指定可选的格式,例如
p/x y
会以十六进制格式显示变量,而不是十进制。其他常用的格式为c(字符),s(字符串),f(浮点型)
2.使用display命令查看变量值
每次遇到断点,只需要键入print命令就能够查看变量值,但是,如果知道会在每次遇到断点时键入这个命令,那么使用
display命令(简写为disp)能节省更多的时间。这个命令要求GDB在执行每次有暂停时就输出指定条目。
使用上面的程序1输出的调试的结果如下:
(gdb) b main
Breakpoint 1 at 0x804839a: file a.c, line 10.
(gdb) b 15
Breakpoint 2 at 0x80483b1: file a.c, line 15.
(gdb) r
Starting program: /root/a.out
Breakpoint 1, main () at a.c:10
10 head.index = 1;
(gdb) disp head
1: head = {index = -1208168460, next = 0x80483d0}
(gdb) c
Continuing.
Breakpoint 2, main () at a.c:15
15 head.index++;
1: head = {index = 1, next = 0x0}
(gdb)
Continuing.
Breakpoint 2, main () at a.c:15
15 head.index++;
1: head = {index = 2, next = 0x0}
(gdb)
Continuing.
Breakpoint 2, main () at a.c:15
15 head.index++;
1: head = {index = 3, next = 0x0}
(gdb)
Breakpoint 1 at 0x804839a: file a.c, line 10.
(gdb) b 15
Breakpoint 2 at 0x80483b1: file a.c, line 15.
(gdb) r
Starting program: /root/a.out
Breakpoint 1, main () at a.c:10
10 head.index = 1;
(gdb) disp head
1: head = {index = -1208168460, next = 0x80483d0}
(gdb) c
Continuing.
Breakpoint 2, main () at a.c:15
15 head.index++;
1: head = {index = 1, next = 0x0}
(gdb)
Continuing.
Breakpoint 2, main () at a.c:15
15 head.index++;
1: head = {index = 2, next = 0x0}
(gdb)
Continuing.
Breakpoint 2, main () at a.c:15
15 head.index++;
1: head = {index = 3, next = 0x0}
(gdb)
可以临时禁用某个显示项,例如:
dis disp 1
临时禁用显示列表中的条目1,条目可以通过 info disp命令检查。
要重新启用条目,使用enable
enable disp 1
要完全删除条目,使用undisplay(简写为undisp)
undisp 1
3.使用call命令调用函数
使用call函数可以调用被调试程序的函数。
使用下面的程序2进行演示:
#include <stdio.h> struct node{ int index; char* content; struct node* next; }; void display(struct node head){ printf("head.index=%d,head.content=%s\n",head.index,head.content); } int main(void) { struct node head; head.index = 1; head.content = "yes"; head.next = NULL; int i; for(i=0; i<3; i++){ head.index++; } display(head); return 0; }
(gdb) b main
Breakpoint 1 at 0x80483f0: file a.c, line 15.
(gdb) r
Starting program: /root/a.out
Breakpoint 1, main () at a.c:15
15 head.index = 1;
(gdb) n
16 head.content = "yes";
(gdb)
17 head.next = NULL;
(gdb)
20 for(i=0; i<3; i++){
(gdb)
21 head.index++;
(gdb) call display(head)
head.index=1,head.content=yes
Breakpoint 1 at 0x80483f0: file a.c, line 15.
(gdb) r
Starting program: /root/a.out
Breakpoint 1, main () at a.c:15
15 head.index = 1;
(gdb) n
16 head.content = "yes";
(gdb)
17 head.next = NULL;
(gdb)
20 for(i=0; i<3; i++){
(gdb)
21 head.index++;
(gdb) call display(head)
head.index=1,head.content=yes
4.使用ptype查看变量类型
使用程序2进行调试:
(gdb) b main
Breakpoint 1 at 0x804842a: file a.c, line 16.
(gdb) r
Starting program: /root/a.out
Breakpoint 1, main () at a.c:16
16 head.index = 1;
(gdb) ptype head
type = struct node {
int index;
char *content;
struct node *next;
}
(gdb)
Breakpoint 1 at 0x804842a: file a.c, line 16.
(gdb) r
Starting program: /root/a.out
Breakpoint 1, main () at a.c:16
16 head.index = 1;
(gdb) ptype head
type = struct node {
int index;
char *content;
struct node *next;
}
(gdb)
5.监视局部变量
使用info locals命令得到当前栈帧中所有局部变量的值列表。
使用程序2进行调试:
(gdb) b main
Breakpoint 1 at 0x804842a: file a.c, line 16.
(gdb) r
Starting program: /root/a.out
Breakpoint 1, main () at a.c:16
16 head.index = 1;
(gdb) info locals
head = {index = -1209402059,
content = 0xb7ff0a50 "U\211\345WV1\366S\350N\212", next = 0x804849b}
i = -1208168460
(gdb) n
17 head.content = "yes";
(gdb)
18 head.next = NULL;
(gdb)
21 for(i=0; i<3; i++){
(gdb) info locals
head = {index = 1, content = 0x8048574 "yes", next = 0x0}
i = -1208168460
(gdb) n
22 head.index++;
(gdb) info local
head = {index = 1, content = 0x8048574 "yes", next = 0x0}
i = 0
(gdb)
Breakpoint 1 at 0x804842a: file a.c, line 16.
(gdb) r
Starting program: /root/a.out
Breakpoint 1, main () at a.c:16
16 head.index = 1;
(gdb) info locals
head = {index = -1209402059,
content = 0xb7ff0a50 "U\211\345WV1\366S\350N\212", next = 0x804849b}
i = -1208168460
(gdb) n
17 head.content = "yes";
(gdb)
18 head.next = NULL;
(gdb)
21 for(i=0; i<3; i++){
(gdb) info locals
head = {index = 1, content = 0x8048574 "yes", next = 0x0}
i = -1208168460
(gdb) n
22 head.index++;
(gdb) info local
head = {index = 1, content = 0x8048574 "yes", next = 0x0}
i = 0
(gdb)
6.检查动态数组
对下面的程序3进行调试。
#include <stdio.h> #include <malloc.h> int main(void){ int a[3] = {1,2,3}; int *b = (int*)malloc(3*sizeof(int)); b[0] = 1; b[1] = 2; b[2] = 3; return 0; }
(gdb) b main
Breakpoint 1 at 0x80483cd: file b.c, line 5.
(gdb) r
Starting program: /root/a.out
Breakpoint 1, main () at b.c:5
5 int a[3] = {1,2,3};
(gdb) n
6 int *b = (int*)malloc(3*sizeof(int));
(gdb)
7 b[0] = 1;
(gdb)
8 b[1] = 2;
(gdb)
9 b[2] = 3;
(gdb)
10 return 0;
(gdb) p a
$1 = {1, 2, 3}
(gdb) p b
$2 = (int *) 0x804b008
(gdb) p *b
$3 = 1
Breakpoint 1 at 0x80483cd: file b.c, line 5.
(gdb) r
Starting program: /root/a.out
Breakpoint 1, main () at b.c:5
5 int a[3] = {1,2,3};
(gdb) n
6 int *b = (int*)malloc(3*sizeof(int));
(gdb)
7 b[0] = 1;
(gdb)
8 b[1] = 2;
(gdb)
9 b[2] = 3;
(gdb)
10 return 0;
(gdb) p a
$1 = {1, 2, 3}
(gdb) p b
$2 = (int *) 0x804b008
(gdb) p *b
$3 = 1
如果是动态数组,直接使用p命令只能打印一个数。
使用如下命令,可以打印出整个数组:
(gdb) p *b@3
$1 = {1, 2, 3}
$1 = {1, 2, 3}
(gdb)
语法如下:
p *pointer@number_of_elements.
另一种方式是使用类型强制转换:
(gdb) p (int [3])*b
$3 = {1, 2, 3}
(gdb)
$3 = {1, 2, 3}
(gdb)
7.设置变量
在gdb中,值的设置非常容易,例如
set x=12
会将x的当前值修改为12.
可以通过gdb的set args命令设置程序的命令行参数,该命令可以需要下次执行run命令时才会发生变化。其实只要在调用
gdb的run命令时使用新参数就能达到同样的效果。
gdb提供info args命令来检查当前函数的参数。
使用下面的程序4进行调试:
#include <stdio.h> void display(int i, char* argv) { printf("argv[%d]=%s\n",i,argv); } int main(int argc, char* argv[]) { int i; for (i=0; i<argc; i++) { display(i,argv[i]); } return 0; }调试:
(gdb) set args 1 2 3
(gdb) b main
Breakpoint 2 at 0x80483f0: file a.c, line 11.
(gdb) b display
Note: breakpoint 1 also set at pc 0x80483ca.
Breakpoint 3 at 0x80483ca: file a.c, line 5.
(gdb) r
Starting program: /root/a.out 1 2 3
Breakpoint 2, main (argc=4, argv=0xbffff724) at a.c:11
11 for (i=0; i<argc; i++) {
(gdb) info args
argc = 4
argv = 0xbffff724
(gdb) c
Continuing.
Breakpoint 1, display (i=0, argv=0xbffff86a "/root/a.out") at a.c:5
5 printf("argv[%d]=%s\n",i,argv);
(gdb) c
Continuing.
argv[0]=/root/a.out
Breakpoint 1, display (i=1, argv=0xbffff876 "1") at a.c:5
5 printf("argv[%d]=%s\n",i,argv);
(gdb)
Continuing.
argv[1]=1
Breakpoint 1, display (i=2, argv=0xbffff878 "2") at a.c:5
5 printf("argv[%d]=%s\n",i,argv);
(gdb)
Continuing.
argv[2]=2
Breakpoint 1, display (i=3, argv=0xbffff87a "3") at a.c:5
5 printf("argv[%d]=%s\n",i,argv);
(gdb)
Continuing.
argv[3]=3
(gdb) b main
Breakpoint 2 at 0x80483f0: file a.c, line 11.
(gdb) b display
Note: breakpoint 1 also set at pc 0x80483ca.
Breakpoint 3 at 0x80483ca: file a.c, line 5.
(gdb) r
Starting program: /root/a.out 1 2 3
Breakpoint 2, main (argc=4, argv=0xbffff724) at a.c:11
11 for (i=0; i<argc; i++) {
(gdb) info args
argc = 4
argv = 0xbffff724
(gdb) c
Continuing.
Breakpoint 1, display (i=0, argv=0xbffff86a "/root/a.out") at a.c:5
5 printf("argv[%d]=%s\n",i,argv);
(gdb) c
Continuing.
argv[0]=/root/a.out
Breakpoint 1, display (i=1, argv=0xbffff876 "1") at a.c:5
5 printf("argv[%d]=%s\n",i,argv);
(gdb)
Continuing.
argv[1]=1
Breakpoint 1, display (i=2, argv=0xbffff878 "2") at a.c:5
5 printf("argv[%d]=%s\n",i,argv);
(gdb)
Continuing.
argv[2]=2
Breakpoint 1, display (i=3, argv=0xbffff87a "3") at a.c:5
5 printf("argv[%d]=%s\n",i,argv);
(gdb)
Continuing.
argv[3]=3
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。