​

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环境


 

  



gdb调试的基本使用_gdb调试

//e.c
#include <stdio.h>
void debug(char *str)
{
printf("debug info :%s\n",str );
}
main(int argc,char *argv[]){
int i,j;
j=0;
for(i=0;i<10;i++){
j+=5;
printf("now a=%d\n", j);
}
}


gdb调试的基本使用_gdb调试


gcc -g -o e e.c

调试gdb e

或者输入gdb

然后 file e

list 命令用法

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



gdb调试的基本使用_gdb调试

gdb) list
1 #include <stdio.h>
2 void debug(char *str)
3 {
4 printf("debug info :%s\n",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)


gdb调试的基本使用_gdb调试


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



gdb调试的基本使用_gdb调试

(gdb) list 8
3 {
4 printf("debug info :%s\n",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=%d\n", j);
12 }
(gdb)


gdb调试的基本使用_gdb调试


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



gdb调试的基本使用_gdb调试

(gdb) list main
1 #include <stdio.h>
2 void debug(char *str)
3 {
4 printf("debug info :%s\n",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)


gdb调试的基本使用_gdb调试


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



gdb调试的基本使用_gdb调试

(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=%d\n", j);
12 }
13 }(gdb) list -
1 #include <stdio.h>
2 void debug(char *str)
3 {
4 printf("debug info :%s\n",str );
(gdb)


gdb调试的基本使用_gdb调试


断点命令break

break location:在location位置设置断点,该位置可以为某一行,某函数名或者其它结构的地址

GDB会在执行该位置的代码之前停下来


gdb调试的基本使用_#include_11 View Code


使用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



gdb调试的基本使用_gdb调试

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


gdb调试的基本使用_gdb调试


display命令

查看参数的值


gdb调试的基本使用_#include_14


gdb调试的基本使用_gdb调试

(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


gdb调试的基本使用_gdb调试


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

step及next命令

step可使得程序逐条执行,即执行完一条语句然后在吓一跳语句前停下来,等待用户的命令

一般使用step命令是,可使用display或者watch命令查看变量的变化,从而判断程序行为是否符合要求

当下一条指令为函数时,s进入函数内部,在其第一条语句前停下来

step n,next n 表示连续但不执行n条指令,如果期间遇到断点,则停下来


gdb调试的基本使用_#include_14


gdb调试的基本使用_gdb调试

(gdb) list
1 #include <stdio.h>
2 void debug(char *str)
3 {
4 printf("debug info :%s\n",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=%d\n", 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=%d\n", j);
(gdb) s
__printf (format=0x400648 "now j=%d\n") at printf.c:30
30 {
(gdb) bt
#0 __printf (format=0x400648 "now j=%d\n") 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=%d\n", j);
(gdb) n
now j=10
13 debug("x=======x");
(gdb) n
debug info :x=======x
10 for(i=0;i<10;i++){
(gdb)


gdb调试的基本使用_gdb调试


watch

watch可设置观察点(watchpoint)。使用观察点可以使得当某表达式的值发生变化时,程序暂停执行。

执行该命令前,必须保证程序已经运行


gdb调试的基本使用_#include_14


gdb调试的基本使用_gdb调试

(gdb) list 
1 #include <stdio.h>
2 void debug(char *str)
3 {
4 printf("debug info :%s\n",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=%d\n", 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=%d\n", 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=%d\n", j);


gdb调试的基本使用_gdb调试


print命令


gdb调试的基本使用_#include_14


gdb调试的基本使用_gdb调试

(gdb) list
1 #include <stdio.h>
2 void debug(char *str)
3 {
4 printf("debug info :%s\n",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=%d\n", 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=%d\n", 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=%d\n", j);
(gdb) p i,j
$2 = 10
(gdb) p j
$3 = 10
(gdb)


gdb调试的基本使用_gdb调试


set var name=value

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

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

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


gdb调试的基本使用_#include_14


gdb调试的基本使用_gdb调试

(gdb) list
1 #include <stdio.h>
2 void debug(char *str)
3 {
4 printf("debug info :%s\n",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=%d\n", 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=%d\n", 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=%d\n", 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=%d\n", 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=%d\n", 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=%d\n", 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=%d\n", 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.


gdb调试的基本使用_gdb调试


函数调用相关的

backtrace

可使用frame 查看堆栈中某一帧的信息


gdb调试的基本使用_#include_14


gdb调试的基本使用_gdb调试

(gdb) list
1 #include <stdio.h>
2 void debug(char *str)
3 {
4 printf("debug info :%s\n",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=%d\n", 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 :%s\n",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 :%s\n") at printf.c:30
30 {
(gdb) bt
#0 __printf (format=0x400638 "debug info :%s\n") 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 :%s\n") 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 :%s\n", ap=0x7fffffffe330) at vfprintf.c:236
236 int save_errno = errno;
(gdb) bt
#0 _IO_vfprintf_internal (s=0x333a58f040, format=0x400638 "debug info :%s\n", 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调试


 GDB段错误调试

所谓段错误就是对内存的非法访问

采用GDB调试段错误有2种方法

1.在GDB中运行目标程序,当发生段错误时,GDB中运行的程序会自动停下来

2.直接运行目标程序,使其在发生段错误时产生内存转储(core dump)文件,GDB对该文件进行调试

abort.c



gdb调试的基本使用_gdb调试

#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();
}


gdb调试的基本使用_gdb调试



gdb调试的基本使用_gdb调试

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函数,产生段错误


gdb调试的基本使用_gdb调试


使用内存转储文件

ulimit -a 



gdb调试的基本使用_gdb调试

[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


gdb调试的基本使用_gdb调试


ulimit -c unlimited  设置为不受限制

 

执行 ./abort 产生内存转储文件

ls 可看到一个名为core且以进程号为后缀的文件

 

core.6289

gdb abort core.6289

bt

方法同上一个gdb调试


人就像是被蒙着眼推磨的驴子,生活就像一条鞭子;当鞭子抽到你背上时,你就只能一直往前走,虽然连你也不知道要走到什么时候为止,便一直这么坚持着。