我是靠谱客的博主 痴情发箍,这篇文章主要介绍gdb调试的基本使用,现在分享给大家,希望可以做个参考。

转:https://www.cnblogs.com/HKUI/p/8955443.html

GDB调试
启动程序准备调试
GDB yourpram
或者
先输入GDB
然后输入 file yourpram

然后使用run或者r命令开始程序的执行,也可以使用 run parameter将参数传递给该程序

参数列表

命令

命令缩写

命令说明

list

l

显示多行源代码

break

b

设置断点,程序运行到断点的位置会停下来

info

i

描述程序的状态

run

r

开始运行程序

display

disp

跟踪查看某个变量,每次停下来都显示它的值

step

s

执行下一条语句,如果该语句为函数调用,则进入函数执行其中的第一条语句

next

n

执行下一条语句,如果该语句为函数调用,不会进入函数内部执行(即不会一步步地调试函数内部语句)

print

p

打印内部变量值

continue

c

继续程序的运行,直到遇到下一个断点

set var name=v

 

设置变量的值

start

st

开始执行程序,在main函数的第一条语句前面停下来

file

 

装入需要调试的程序

kill

k

终止正在调试的程序

watch

 

监视变量值的变化

backtrace

bt

查看函数调用信息(堆栈)

frame

f

查看栈帧  f n 切换到编号为n的栈

quit

q

退出GDB环境

 

  

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//e.c #include <stdio.h> void debug(char *str) { printf("debug info :%sn",str ); } main(int argc,char *argv[]){ int i,j; j=0; for(i=0;i<10;i++){ j+=5; printf("now a=%dn", j); } }

复制代码

gcc -g -o e e.c
调试gdb e
或者输入gdb
然后 file e

list 命令用法

list命令显示多行源代码,从上次的位置开始显示,默认情况下,一次显示10行,第一次使用时,从代码起始位置显示

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%sn",str ); 5 } 6 main(int argc,char *argv[]){ 7 int i,j; 8 j=0; 9 for(i=0;i<10;i++){ 10 j+=5; (gdb)

复制代码

list n显示已第n行未中心的10行代码

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
(gdb) list 8 3 { 4 printf("debug info :%sn",str ); 5 } 6 main(int argc,char *argv[]){ 7 int i,j; 8 j=0; 9 for(i=0;i<10;i++){ 10 j+=5; 11 printf("now a=%dn", j); 12 } (gdb)

复制代码

list functionname显示以functionname的函数为中心的10行代码

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
(gdb) list main 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%sn",str ); 5 } 6 main(int argc,char *argv[]){ 7 int i,j; 8 j=0; 9 for(i=0;i<10;i++){ 10 j+=5; (gdb)

复制代码

list - 显示刚才打印过的源代码之前的代码

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(gdb) list 10 5 } 6 main(int argc,char *argv[]){ 7 int i,j; 8 j=0; 9 for(i=0;i<10;i++){ 10 j+=5; 11 printf("now a=%dn", j); 12 } 13 }(gdb) list - 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%sn",str ); (gdb)

复制代码

断点命令break
break location:在location位置设置断点,该位置可以为某一行,某函数名或者其它结构的地址
GDB会在执行该位置的代码之前停下来

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%sn",str ); 5 } 6 main(int argc,char *argv[]){ 7 int i,j; 8 j=0; 9 for(i=0;i<10;i++){ 10 j+=5; (gdb) 11 printf("now a=%dn", j); 12 } 13 }(gdb) break 10 Breakpoint 1 at 0x40050a: file e.c, line 10. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10 10 j+=5; (gdb) c Continuing. now a=5 Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10 10 j+=5; (gdb) c Continuing. now a=10 Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10 10 j+=5; (gdb)

复制代码

使用delete breakpoints 断点号 删除断点
这里的断点号表示的是第几个断点,刚才执行break 10返回 reakpoint 1 at 0x40050a: file e.c, line 10.
中的1表示该断点的标号,因此使用 delete breakpoints 1表示删除第10行所定义的断点
clear n表示清除第n行的断点,因此clear 10等同于delete breakpoints 1
disable/enable n表示使得编号为n的断点暂时失效或有效
可使用info查看断点相关的信息
info breakpoints

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
gdb) info breakpoints No breakpoints or watchpoints. (gdb) break 10 Breakpoint 2 at 0x40050a: file e.c, line 10. (gdb) break 9 Breakpoint 3 at 0x400501: file e.c, line 9. (gdb) info breakpoints Num Type Disp Enb Address What 2 breakpoint keep y 0x000000000040050a in main at e.c:10 3 breakpoint keep y 0x0000000000400501 in main at e.c:9

复制代码

display命令
查看参数的值

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
(gdb) break 10 Breakpoint 1 at 0x40050a: file e.c, line 10. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10 10 j+=5; (gdb) display j 1: j = 0 (gdb) c Continuing. now a=5 Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10 10 j+=5; 1: j = 5 (gdb) display 1: j = 5 (gdb) display i 2: i = 1 (gdb) display j 3: j = 5 (gdb) display j*2 4: j*2 = 10 (gdb) info display Auto-display expressions now in effect: Num Enb Expression 4: y j*2 3: y j 2: y i 1: y j

复制代码

也可以使用disable,enable,delete,info命令修改及查看其状态,用法与对断点的一样

step及next命令
step可使得程序逐条执行,即执行完一条语句然后在吓一跳语句前停下来,等待用户的命令
一般使用step命令是,可使用display或者watch命令查看变量的变化,从而判断程序行为是否符合要求
当下一条指令为函数时,s进入函数内部,在其第一条语句前停下来
step n,next n 表示连续但不执行n条指令,如果期间遇到断点,则停下来

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
(gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%sn",str ); 5 } 6 7 main(int argc,char *argv[]){ 8 int i,j; 9 j=0; 10 for(i=0;i<10;i++){ (gdb) 11 j+=5; 12 printf("now j=%dn", j); 13 debug("x=======x"); 14 } 15 }(gdb) Line number 16 out of range; e.c has 15 lines. (gdb) break 11 Breakpoint 1 at 0x40050a: file e.c, line 11. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e1 Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:11 11 j+=5; (gdb) s 12 printf("now j=%dn", j); (gdb) s __printf (format=0x400648 "now j=%dn") at printf.c:30 30 { (gdb) bt #0 __printf (format=0x400648 "now j=%dn") at printf.c:30 #1 0x0000000000400525 in main (argc=1, argv=0x7fffffffe538) at e.c:12 (gdb) n 34 va_start (arg, format); (gdb) n 35 done = vfprintf (stdout, format, arg); (gdb) n now j=5 39 } (gdb) bt #0 __printf (format=<value optimized out>) at printf.c:39 #1 0x0000000000400525 in main (argc=1, argv=0x7fffffffe538) at e.c:12 (gdb) n main (argc=1, argv=0x7fffffffe538) at e.c:13 13 debug("x=======x"); (gdb) n debug info :x=======x 10 for(i=0;i<10;i++){ (gdb) s Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:11 11 j+=5; (gdb) s 12 printf("now j=%dn", j); (gdb) n now j=10 13 debug("x=======x"); (gdb) n debug info :x=======x 10 for(i=0;i<10;i++){ (gdb)

复制代码

watch
watch可设置观察点(watchpoint)。使用观察点可以使得当某表达式的值发生变化时,程序暂停执行。
执行该命令前,必须保证程序已经运行

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
(gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%sn",str ); 5 } 6 7 main(int argc,char *argv[]){ 8 int i,j; 9 j=0; 10 for(i=0;i<10;i++){ (gdb) 11 j+=5; 12 printf("now j=%dn", j); 13 debug("x=======x"); 14 } 15 }(gdb) Line number 16 out of range; e.c has 15 lines. (gdb) b main Breakpoint 1 at 0x4004fa: file e.c, line 9. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e1 Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:9 9 j=0; (gdb) watch j Hardware watchpoint 2: j (gdb) c Continuing. Hardware watchpoint 2: j Old value = 0 New value = 5 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%dn", j); (gdb) c Continuing. now j=5 debug info :x=======x Hardware watchpoint 2: j Old value = 5 New value = 10 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%dn", j);

复制代码

print命令

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
(gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%sn",str ); 5 } 6 7 main(int argc,char *argv[]){ 8 int i,j; 9 j=0; 10 for(i=0;i<10;i++){ (gdb) 11 j+=5; 12 printf("now j=%dn", j); 13 debug("x=======x"); 14 } 15 }(gdb) Line number 16 out of range; e.c has 15 lines. (gdb) break 12 Breakpoint 1 at 0x40050e: file e.c, line 12. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e1 Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%dn", j); (gdb) p j $1 = 5 (gdb) c Continuing. now j=5 debug info :x=======x Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%dn", j); (gdb) p i,j $2 = 10 (gdb) p j $3 = 10 (gdb)

复制代码

set var name=value

set args 可指定运行时参数(当main函数需要参数时 如:set args 10 20 30 40 50)

show args 命令可以查看设置好的运行参数


在程序运行中动态改变变量的值

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
(gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%sn",str ); 5 } 6 7 main(int argc,char *argv[]){ 8 int i,j; 9 j=0; 10 for(i=0;i<10;i++){ (gdb) 11 j+=5; 12 printf("now j=%dn", j); 13 debug("x=======x"); 14 } 15 }(gdb) Line number 16 out of range; e.c has 15 lines. (gdb) break main Breakpoint 1 at 0x4004fa: file e.c, line 9. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e1 Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:9 9 j=0; (gdb) watch i Hardware watchpoint 2: i (gdb) watch j Hardware watchpoint 3: j (gdb) c Continuing. Hardware watchpoint 3: j Old value = 0 New value = 5 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%dn", j); (gdb) c Continuing. now j=5 debug info :x=======x Hardware watchpoint 2: i Old value = 0 New value = 1 0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10 10 for(i=0;i<10;i++){ (gdb) c Continuing. Hardware watchpoint 3: j Old value = 5 New value = 10 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%dn", j); (gdb) c Continuing. now j=10 debug info :x=======x Hardware watchpoint 2: i Old value = 1 New value = 2 0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10 10 for(i=0;i<10;i++){ (gdb) c Continuing. Hardware watchpoint 3: j Old value = 10 New value = 15 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%dn", j); (gdb) c Continuing. now j=15 debug info :x=======x Hardware watchpoint 2: i Old value = 2 New value = 3 0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10 10 for(i=0;i<10;i++){ (gdb) c Continuing. Hardware watchpoint 3: j Old value = 15 New value = 20 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%dn", j); (gdb) c Continuing. now j=20 debug info :x=======x Hardware watchpoint 2: i Old value = 3 New value = 4 0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10 10 for(i=0;i<10;i++){ (gdb) set var i=8 (gdb) c Continuing. Hardware watchpoint 3: j Old value = 20 New value = 25 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%dn", j); (gdb) c Continuing. now j=25 debug info :x=======x Hardware watchpoint 2: i Old value = 8 New value = 9 0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10 10 for(i=0;i<10;i++){ (gdb) c Continuing. Hardware watchpoint 3: j Old value = 25 New value = 30 main (argc=1, argv=0x7fffffffe538) at e.c:12 12 printf("now j=%dn", j); (gdb) c Continuing. now j=30 debug info :x=======x Hardware watchpoint 2: i Old value = 9 New value = 10 0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10 10 for(i=0;i<10;i++){ (gdb) c Continuing. 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. __libc_start_main (main=0x4004eb <main>, argc=1, ubp_av=0x7fffffffe538, init=<value optimized out>, fini=<value optimized out>, rtld_fini=<value optimized out>, stack_end=0x7fffffffe528) at libc-start.c:258 258 exit (result); (gdb) c Continuing. Program exited with code 026.

复制代码

函数调用相关的
backtrace
可使用frame 查看堆栈中某一帧的信息

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
(gdb) list 1 #include <stdio.h> 2 void debug(char *str) 3 { 4 printf("debug info :%sn",str ); 5 } 6 7 main(int argc,char *argv[]){ 8 int i,j; 9 j=0; 10 for(i=0;i<10;i++){ (gdb) 11 j+=5; 12 printf("now j=%dn", j); 13 debug("x=======x"); 14 } 15 }(gdb) Line number 16 out of range; e.c has 15 lines. (gdb) b 13 Breakpoint 1 at 0x400525: file e.c, line 13. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/e1 now j=5 Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:13 13 debug("x=======x"); (gdb) s debug (str=0x400652 "x=======x") at e.c:4 4 printf("debug info :%sn",str ); (gdb) bt #0 debug (str=0x400652 "x=======x") at e.c:4 #1 0x000000000040052f in main (argc=1, argv=0x7fffffffe538) at e.c:13 (gdb) s __printf (format=0x400638 "debug info :%sn") at printf.c:30 30 { (gdb) bt #0 __printf (format=0x400638 "debug info :%sn") at printf.c:30 #1 0x00000000004004e9 in debug (str=0x400652 "x=======x") at e.c:4 #2 0x000000000040052f in main (argc=1, argv=0x7fffffffe538) at e.c:13 (gdb) s 34 va_start (arg, format); (gdb) bt #0 __printf (format=0x400638 "debug info :%sn") at printf.c:34 #1 0x00000000004004e9 in debug (str=0x400652 "x=======x") at e.c:4 #2 0x000000000040052f in main (argc=1, argv=0x7fffffffe538) at e.c:13 (gdb) s 35 done = vfprintf (stdout, format, arg); (gdb) s _IO_vfprintf_internal (s=0x333a58f040, format=0x400638 "debug info :%sn", ap=0x7fffffffe330) at vfprintf.c:236 236 int save_errno = errno; (gdb) bt #0 _IO_vfprintf_internal (s=0x333a58f040, format=0x400638 "debug info :%sn", ap=0x7fffffffe330) at vfprintf.c:236 #1 0x000000333a24effa in __printf (format=<value optimized out>) at printf.c:35 #2 0x00000000004004e9 in debug (str=0x400652 "x=======x") at e.c:4 #3 0x000000000040052f in main (argc=1, argv=0x7fffffffe538) at e.c:13 (gdb) c Continuing. debug info :x=======x now j=10 Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:13 13 debug("x=======x"); (gdb) bt #0 main (argc=1, argv=0x7fffffffe538) at e.c:13

复制代码

 GDB段错误调试

所谓段错误就是对内存的非法访问
采用GDB调试段错误有2种方法
1.在GDB中运行目标程序,当发生段错误时,GDB中运行的程序会自动停下来
2.直接运行目标程序,使其在发生段错误时产生内存转储(core dump)文件,GDB对该文件进行调试

abort.c

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h> #include <stdlib.h> void recurse(void) { static int i; if( ++i == 3) abort(); else recurse(); } int main(int argc,char ** argv){ recurse(); }

复制代码

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
gcc -g -o abort abort.c 使用gdb调试 Line number 15 out of range; abort.c has 14 lines. (gdb) r Starting program: /mnt/hgfs/www/c/gcc/abort Program received signal SIGABRT, Aborted. 0x000000333a232495 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 64 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); (gdb) bt #0 0x000000333a232495 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 #1 0x000000333a233c75 in abort () at abort.c:92 #2 0x00000000004004e7 in recurse () at abort.c:8 #3 0x00000000004004ec in recurse () at abort.c:10 #4 0x00000000004004ec in recurse () at abort.c:10 #5 0x0000000000400502 in main (argc=1, argv=0x7fffffffe528) at abort.c:13 显示在recurse函数调用了3次后调用了abort函数,产生段错误

复制代码

使用内存转储文件

ulimit -a 

复制代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@centos1 gcc]# ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 7331 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 10240 cpu time (seconds, -t) unlimited max user processes (-u) 7331 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited core file size 此时是0

复制代码

ulimit -c unlimited  设置为不受限制

 

执行 ./abort 产生内存转储文件
ls 可看到一个名为core且以进程号为后缀的文件

 

core.6289
gdb abort core.6289
bt
方法同上一个gdb调试

最后

以上就是痴情发箍最近收集整理的关于gdb调试的基本使用的全部内容,更多相关gdb调试内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部