时隔半年,终于再次鼓起勇气,开始准备着手记录点什么。从今年三月开始到现在,就一直没有写过任何博客,记录下任何知识。其中有一大部分原因是因为自己克制力太差的原因,即使是这么有兴趣的事情自己还是没能每天持之以恒的坚持。以后会尽量避免,坚持每天都能越来越好一点。自己之所以选择在这么偏僻(没人会来看)的一个地方记录自己所学,而没有选择在CSDN 博客园之类的搜索引擎很容易找到的地方,还是之前原因。自己所学的这些基础,不足挂齿,百度一下千篇一律的文章,我的就不上去献丑了。在这僻静之地留我自己偶尔看看巩固一下即可。。。不碎碎念了,接下来记录一下这两天重新看过的GDB

GDB调试

因为我个人对GDB所有知识点并不是那种形成体系的熟练,只是遇到问题大概记得用某几个命令来调试而已,所以不能有很好的命令总结之类的描述。只能够写一个例子代码,来进行命令的演示调试。内容大部分完全来自于我对<<Linux网络编程>>这本书的学习。
首先写下我们用来做GDB演示的代码,文件名 gdb_test.c :

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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int sum(unsigned int n);
void usage();

typedef struct Tag_IO{
int value;
int result;
}stIO;

int main(int argc, char *argv[]){
stIO io;
int value;
if(argc != 2){
usage();
exit(-1);
}
memset(&io, 0, sizeof(io));

io.value = atoi(argv[1]);
io.result = sum(io.value);
printf("输出: %d\n", io.result);
return 0;
}

int sum(unsigned int n){
int i;
int result = 0;
for(i=0; i<n; ++i){
result +=i;
}
return result;
}

void usage(){
printf("./gdb_test [value]\n");
printf("Example: ./gdb_test 3\n");
}

使用命令 gcc -g gdb_test.c -o gdb_test 编译出可执行二进制文件,加上-g参数是为了编译出debug版本,否则不可以使用gdb调试.
接下来介绍一些调试命令细节

  • gdb [可以执行程序名] 进入调试模式

hongning@ubuntu:~/C_Study/day10-GDB$ gdb gdb_test
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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 “x86_64-linux-gnu”.
Type “show configuration” for configuration details.
For bug reporting instructions, please see:
http://www.gnu.org/software/gdb/bugs/.
Find the GDB manual and other documentation resources online at:
http://www.gnu.org/software/gdb/documentation/.
For help, type “help”.
Type “apropos word” to search for commands related to “word”…
Reading symbols from gdb_test…done.
(gdb)

  • set args 设置命令行参数

(gdb) set args 3

  • list(可以缩写为l) 打印代码内容,可以通过设置调整显示行数,也可以不断通过list命令往下查看代码

(gdb) l
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 int sum(unsigned int n);
6 void usage();
7
8 typedef struct Tag_IO{
9 int value;
10 int result;

  • b 设置断点

(gdb) b 32
Breakpoint 1 at 0x40076d: file gdb_test.c, line 32.

  • run 运行程序,因为之前设置了断点,和命令行参数.所以暂停在32行

(gdb) run
Starting program: /home/hongning/C_Study/day10-GDB/gdb_test 3

Breakpoint 1, sum (n=3) at gdb_test.c:32
32 result +=i;

  • display 显示变量,每次运行暂停时都会显示设置的变量值,比print更方便调试

(gdb) display i
1: i = 0
(gdb) display result
2: result = 0
(gdb) c
Continuing.

Breakpoint 1, sum (n=3) at gdb_test.c:32
32 result +=i;
1: i = 1
2: result = 0
(gdb)
Continuing.

Breakpoint 1, sum (n=3) at gdb_test.c:32
32 result +=i;
1: i = 2
2: result = 1

  • set 可以修改变量的值,强制修改result的值

(gdb) set result=99
(gdb) c
Continuing.
输出: 101

以上列出了一些简单的命令调试,gdb还可以不带参数执行,然后在内部通过file指定运行程序

hongning@ubuntu:~/C_Study/day10-GDB$ gdb
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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 “x86_64-linux-gnu”.
Type “show configuration” for configuration details.
For bug reporting instructions, please see:
http://www.gnu.org/software/gdb/bugs/.
Find the GDB manual and other documentation resources online at:
http://www.gnu.org/software/gdb/documentation/.
For help, type “help”.
Type “apropos word” to search for commands related to “word”.
(gdb) file gdb_test
Reading symbols from gdb_test…done.
(gdb)

然后通过 run命令加参数方式直接运行

(gdb) run 3
Starting program: /home/hongning/C_Study/day10-GDB/gdb_test 3
输出: 3

  • 参数设置和显示

使用set args命令设置参数,使用show args 显示参数

(gdb) show args
Argument list to give program being debugged when it is started is “3”.

也可以通过 list line1,line2 指定显示行数的代码

(gdb) l 2,30
2 #include <stdlib.h>
3 #include <string.h>
4
5 int sum(unsigned int n);
6 void usage();
7
8 typedef struct Tag_IO{
9 int value;
10 int result;
11 }stIO;
12
13 int main(int argc, char *argv[]){
14 stIO io;
15 int value;
16 if(argc != 2){
17 usage();
18 exit(-1);
19 }
20 memset(&io, 0, sizeof(io));
21
22 io.value = atoi(argv[1]);
23 io.result = sum(io.value);
24 printf(“输出: %d\n”, io.result);
25 return 0;
26 }
27
28 int sum(unsigned int n){
29 int i;
30 int result = 0;

  • 打印数据
  • p 变量名 打印变量的值

(gdb) p result
$1 = ‘\000’

  • 打印函数调用返回值

(gdb) p sum(3)
$1 = 3
(gdb) p sum(4)
$2 = 6

  • 打印结构体变量的值

(gdb) p io
$3 = {value = 3, result = 3}

打印指针变量内部值,在指针变量前加*就可以了,打印变量地址在变量前面加&

(gdb) p &io
$4 = (stIO *) 0x7fffffffe200

  • 设置断点
  • break 行号
  • break 函数名称
  • break 行号 if条件
    这里演示一下第三种条件断点情况

(gdb) file gdb
Reading symbols from gdb…(no debugging symbols found)…done.
(gdb) file gdb_test
Reading symbols from gdb_test…done.
(gdb) set args 3
(gdb) break 32 if i==2
Breakpoint 1 at 0x40076d: file gdb_test.c, line 32.
(gdb) run
Starting program: /home/hongning/C_Study/day10-GDB/gdb_test 3

Breakpoint 1, sum (n=3) at gdb_test.c:32
32 result +=i;
(gdb) p i
$1 = 2

通过上面例子可以看出i==0 和i==1的时候并没有触发断点

  • 显示断点信息
  • info break

(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000040076d in sum at gdb_test.c:32
stop only if i==2
breakpoint already hit 1 time

Num列是断点编号,可以通过delete b 编号删除断点

(gdb) delete break 1
(gdb) info break
No breakpoints or watchpoints.

还可以通过disable命令禁用断点

(gdb) break 32 if i==2
Breakpoint 2 at 0x40076d: file gdb_test.c, line 32.
(gdb) info break
Num Type Disp Enb Address What
2 breakpoint keep y 0x000000000040076d in sum at gdb_test.c:32
stop only if i==2
(gdb) disable break 2
(gdb) info break
Num Type Disp Enb Address What
2 breakpoint keep n 0x000000000040076d in sum at gdb_test.c:32
stop only if i==2

通过enable命令开启被禁用的断点

(gdb) enable break 2
(gdb) info break
Num Type Disp Enb Address What
2 breakpoint keep y 0x000000000040076d in sum at gdb_test.c:32
stop only if i==2

以上演示应该注意的是Enb列的值,y代表断点可用,n是不可用

  • 显示变量类型
  • whatis 命令显示类型

(gdb) whatis io
type = stIO
(gdb) whatis argc
type = int
(gdb) whatis argv
type = char **

  • ptype 命令还可以显示结构体内部结构

(gdb) ptype io
type = struct Tag_IO {
int value;
int result;
}

  • 单步调试
  • start单步执行程序
  • next单步跟踪,也就是一行一行执行程序
  • step 当遇到函数调用,step命令可以进入调用函数内部
  • finsh 想退出调用函数内部,使用finish命令就可以了

  • 调用路径

  • backtrace 显示函数调用路径信息,简写为bt

时间太晚了,后边记录很匆忙,这几条命令我自己用的也比较多,不容易忘记,个人感觉不需要过多演示,下一节准备简单介绍一下多线程调试,多进程调试