Linux c编程之gdb

一、说明

  gdb是linux或unix平台的程序调试工具。不同于IDE调试工具,是一个命令行调式工具。
一般来说,gdb主要帮助你完成下面四个方面的功能:
1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3、当程序被停住时,可以检查此时你的程序中所发生的事。
4、你可以改变你的程序,将一个BUG产生的影响修正从而测试其他BUG。

二、gdb 调试启动

源码示例:
hello_world_main.c:

#include <stdio.h>
#include <pthread.h>

#define MAX_CNT 5

int show_str(char *str)
{
    printf("str: [%s]\n", str);

    return 0;
}

int main(int argc, char *argv[])
{
    char *str = "hello world";
    int i = 0;
    int sum = 0;

    show_str(str);

    for (i = 0; i < MAX_CNT; i++) {
        sum += i;
    }

    printf("sum:%d\n", sum);

    return 0;
}

加入-g选项编译出的可执行文件才能使用gdb进行调试

  1. 编译程序时没有-g选项时,无法加载符号信息,因此无法调试
$gcc hello_world_main.c
$ gdb a.out
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 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 a.out...(no debugging symbols found)...done.
(gdb)
  • 编译程序时添加-g选项时
$gcc hello_world_main.c -g
$ gdb a.out 
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 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 a.out...done.
(gdb)

三、常见调试命令

  • clear N
    删除N行断点
  • delete N
    删除N号断点
  • delete
    删除所有断点
  • disable xxx
    失能断点
  • enable xxx
    使能断点
  • info b
    查看断点
  • info thread
    查看线程信息
  • list linenum
    以linenum指定的行号为中心,显示10行
  • list function
    以指定的函数为中心,显示10行
  • bt
    查看函数back trace
  • pwd
    查看程序路径
  • ctrl+p
    前一条命令
  • ctrl+n
    下一条命令
  • set args
    设置运行程序时的命令行参数,如:set args 33 55

四、实例解析

4.1 查看源代码

使用list(简写l)命令可以查看源代码
(gdb) list
6	int show_str(char *str)
7	{
8	    printf("str: [%s]\n", str);
9	
10	    return 0;
11	}
12	
13	int main(int argc, char *argv[])
14	{
15	    char *str = "hello world";
(gdb) l
16	    int i = 0;
17	    int sum = 0;
18	
19	    show_str(str);
20	
21	    for (i = 0; i < MAX_CNT; i++) {
22	        sum += i;
23	    }
24	
25	    printf("sum:%d\n", sum);

4.2 使用回车键执行上一条命令

(gdb) l
6	int show_str(char *str)
7	{
8	    printf("str: [%s]\n", str);
9	
10	    return 0;
11	}
12	
13	int main(int argc, char *argv[])
14	{
15	    char *str = "hello world";
(gdb) 
16	    int i = 0;
17	    int sum = 0;
18	
19	    show_str(str);
20	
21	    for (i = 0; i < MAX_CNT; i++) {
22	        sum += i;
23	    }
24	
25	    printf("sum:%d\n", sum);

4.3 运行程序

run:运行程序,简写为r

$ gdb a.out 
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 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 a.out...done.
(gdb) r
Starting program: /home/zorro/voip/Shengy-st/linux-c-demo/041-1-gdb-basic/a.out 
str: [hello world]
sum:10
[Inferior 1 (process 24765) exited normally]
(gdb)

4.4 断点

设置断点是gdb调试的重要功能。在调试过程中,想要获取程序在某个位置 的运行状态或控制程序运行逻辑,就需要依赖断点。可以增加断点,删除断点,查看断点
添加断点:break命令,简写为b. 可以按行号或函数名称添加断点,比如b 16或b function
查看断点:info 命令,简写为i. 比如info b 或 i b
删除断点:delete 命令,简写为d. delete +断点号 比如,d 2

$ gdb a.out 
Reading symbols from a.out...done.
(gdb) l
6	int show_str(char *str)
7	{
8	    printf("str: [%s]\n", str);
9	
10	    return 0;
11	}
12	
13	int main(int argc, char *argv[])
14	{
15	    char *str = "hello world";
(gdb) l
16	    int i = 0;
17	    int sum = 0;
18	
19	    show_str(str);
20	
21	    for (i = 0; i < MAX_CNT; i++) {
22	        sum += i;
23	    }
24	
25	    printf("sum:%d\n", sum);
(gdb) b 21
Breakpoint 1 at 0x400587: file hello_world_main.c, line 21.
(gdb) b show_str
Breakpoint 2 at 0x400539: file hello_world_main.c, line 8.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400587 in main at hello_world_main.c:21
2       breakpoint     keep y   0x0000000000400539 in show_str at hello_world_main.c:8
(gdb) d 1
(gdb) info b
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x0000000000400539 in show_str at hello_world_main.c:8
(gdb)

4.5 查看变量值

查看信息使用print,简写为p

$ gdb a.out 
(gdb) l
6	int show_str(char *str)
7	{
8	    printf("str: [%s]\n", str);
9	
10	    return 0;
11	}
12	
13	int main(int argc, char *argv[])
14	{
15	    char *str = "hello world";
(gdb) 
16	    int i = 0;
17	    int sum = 0;
18	
19	    show_str(str);
20	
21	    for (i = 0; i < MAX_CNT; i++) {
22	        sum += i;
23	    }
24	
25	    printf("sum:%d\n", sum);
(gdb) b 25
Breakpoint 1 at 0x4005a0: file hello_world_main.c, line 25.
(gdb) r
Starting program: /home/zorro/voip/Shengy-st/linux-c-demo/041-1-gdb-basic/a.out 
str: [hello world]

Breakpoint 1, main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:25
25	    printf("sum:%d\n", sum);
(gdb) p sum
$1 = 10
(gdb) p i
$2 = 5
(gdb) p str
$3 = 0x40064f "hello world"
(gdb)  p &i
$4 = (int *) 0x7fffffffdcb0

4.6 重新运行

使用r命令可以使调试中的程序从头运行,不会删除之前的断点

$ gdb a.out 
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 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 a.out...done.
(gdb) b 19
Breakpoint 1 at 0x40057b: file hello_world_main.c, line 19.
(gdb) r
Starting program: /home/zorro/voip/Shengy-st/linux-c-demo/041-1-gdb-basic/a.out 

Breakpoint 1, main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:19
19	    show_str(str);

4.7 继续运行

继续运行命令continue,简写为c

$ gdb a.out 
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 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 a.out...done.
(gdb) b 19
Breakpoint 1 at 0x40057b: file hello_world_main.c, line 19.
(gdb) r
Starting program: /home/zorro/voip/Shengy-st/linux-c-demo/041-1-gdb-basic/a.out 

Breakpoint 1, main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:19
19	    show_str(str);
(gdb) c
Continuing.
str: [hello world]
sum:10
[Inferior 1 (process 25069) exited normally]

4.8 单步调试n

n命令不会进入到函数的内部

$ gdb a.out 
Reading symbols from a.out...done.
(gdb) l
6	int show_str(char *str)
7	{
8	    printf("str: [%s]\n", str);
9	
10	    return 0;
11	}
12	
13	int main(int argc, char *argv[])
14	{
15	    char *str = "hello world";
(gdb) l
16	    int i = 0;
17	    int sum = 0;
18	
19	    show_str(str);
20	
21	    for (i = 0; i < MAX_CNT; i++) {
22	        sum += i;
23	    }
24	
25	    printf("sum:%d\n", sum);
(gdb) b 19
Breakpoint 1 at 0x40057b: file hello_world_main.c, line 19.
(gdb) r
Starting program: /home/zorro/voip/Shengy-st/linux-c-demo/041-1-gdb-basic/a.out 

Breakpoint 1, main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:19
19	    show_str(str);
(gdb) n
str: [hello world]
21	    for (i = 0; i < MAX_CNT; i++) {
(gdb) n
22	        sum += i;
(gdb)

4.9 单步调试s

$ gdb a.out 
(gdb) l
6	int show_str(char *str)
7	{
8	    printf("str: [%s]\n", str);
9	
10	    return 0;
11	}
12	
13	int main(int argc, char *argv[])
14	{
15	    char *str = "hello world";
(gdb) l
16	    int i = 0;
17	    int sum = 0;
18	
19	    show_str(str);
20	
21	    for (i = 0; i < MAX_CNT; i++) {
22	        sum += i;
23	    }
24	
25	    printf("sum:%d\n", sum);
(gdb) b show_str
Breakpoint 1 at 0x400539: file hello_world_main.c, line 8.
(gdb) r
Starting program: /home/zorro/voip/Shengy-st/linux-c-demo/041-1-gdb-basic/a.out 

Breakpoint 1, show_str (str=0x40064f "hello world") at hello_world_main.c:8
8	    printf("str: [%s]\n", str);
(gdb) s
__printf (format=0x400644 "str: [%s]\n") at printf.c:28
28	printf.c: No such file or directory.
(gdb) 

4.10 查看当前调用栈

(gdb) bt
#0  __printf (format=0x400644 "str: [%s]\n") at printf.c:28
#1  0x000000000040054f in show_str (str=0x40064f "hello world") at hello_world_main.c:8
#2  0x0000000000400587 in main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:19

4.11 从当前函数返回

从当前函数返回使用finish命令

(gdb) bt
#0  __printf (format=0x400644 "str: [%s]\n") at printf.c:28
#1  0x000000000040054f in show_str (str=0x40064f "hello world") at hello_world_main.c:8
#2  0x0000000000400587 in main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:19
(gdb) finish
Run till exit from #0  __printf (format=0x400644 "str: [%s]\n") at printf.c:28
str: [hello world]
show_str (str=0x40064f "hello world") at hello_world_main.c:10
10	    return 0;
Value returned is $1 = 19
(gdb) bt
#0  show_str (str=0x40064f "hello world") at hello_world_main.c:10
#1  0x0000000000400587 in main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:19

4.12 修改变量值

$ gdb a.out 
(gdb) l
6	int show_str(char *str)
7	{
8	    printf("str: [%s]\n", str);
9	
10	    return 0;
11	}
12	
13	int main(int argc, char *argv[])
14	{
15	    char *str = "hello world";
(gdb) l
16	    int i = 0;
17	    int sum = 0;
18	
19	    show_str(str);
20	
21	    for (i = 0; i < MAX_CNT; i++) {
22	        sum += i;
23	    }
24	
25	    printf("sum:%d\n", sum);
(gdb) b 19
Breakpoint 1 at 0x40057b: file hello_world_main.c, line 19.
(gdb) r
Starting program: /home/zorro/voip/Shengy-st/linux-c-demo/041-1-gdb-basic/a.out 

Breakpoint 1, main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:19
19	    show_str(str);
(gdb) p i
$1 = 0
(gdb) p i=4
$2 = 4
(gdb) p i
$3 = 4

4.13 监控变量的变化

$ gdb a.out 
(gdb) l
6	int show_str(char *str)
7	{
8	    printf("str: [%s]\n", str);
9	
10	    return 0;
11	}
12	
13	int main(int argc, char *argv[])
14	{
15	    char *str = "hello world";
(gdb) l
16	    int i = 0;
17	    int sum = 0;
18	
19	    show_str(str);
20	
21	    for (i = 0; i < MAX_CNT; i++) {
22	        sum += i;
23	    }
24	
25	    printf("sum:%d\n", sum);
(gdb) b 21
Breakpoint 1 at 0x400587: file hello_world_main.c, line 21.
(gdb) r
Starting program: /home/zorro/voip/Shengy-st/linux-c-demo/041-1-gdb-basic/a.out 
str: [hello world]

Breakpoint 1, main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:21
21	    for (i = 0; i < MAX_CNT; i++) {
(gdb) p sum
$1 = 0
(gdb) watch sum
Hardware watchpoint 2: sum
(gdb) c
Continuing.
Hardware watchpoint 2: sum

Old value = 0
New value = 1
main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:21
21	    for (i = 0; i < MAX_CNT; i++) {
(gdb) p i
$2 = 1
(gdb) c
Continuing.
Hardware watchpoint 2: sum

Old value = 1
New value = 3
main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:21
21	    for (i = 0; i < MAX_CNT; i++) {
(gdb)

4.14 退出gdb调试

使用quit或q退出gdb调试

$ gdb a.out 
(gdb) b 19
Breakpoint 1 at 0x40057b: file hello_world_main.c, line 19.
(gdb) r
Starting program: /home/zorro/voip/Shengy-st/linux-c-demo/041-1-gdb-basic/a.out 

Breakpoint 1, main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:19
19	    show_str(str);
(gdb) quit
A debugging session is active.

	Inferior 1 [process 25148] will be killed.

Quit anyway? (y or n) y

4.15 查看当前运行位置where

$ gdb a.out 
(gdb) b 19
Breakpoint 1 at 0x40057b: file hello_world_main.c, line 19.
(gdb) r
Starting program: /home/zorro/voip/Shengy-st/linux-c-demo/041-1-gdb-basic/a.out 

Breakpoint 1, main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:19
19	    show_str(str);
(gdb) s
show_str (str=0x40064f "hello world") at hello_world_main.c:8
8	    printf("str: [%s]\n", str);
(gdb) where
#0  show_str (str=0x40064f "hello world") at hello_world_main.c:8
#1  0x0000000000400587 in main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:19
(gdb) bt
#0  show_str (str=0x40064f "hello world") at hello_world_main.c:8
#1  0x0000000000400587 in main (argc=1, argv=0x7fffffffdda8) at hello_world_main.c:19
(gdb) 

4.16 gdb 传递参数

源码:
hello_world_main.c:

#include <stdio.h>
#include <pthread.h>

#define MAX_CNT 5

int show_str(char *str)
{
    printf("str: [%s]\n", str);

    return 0;
}

int main(int argc, char *argv[])
{
    int i = 0;
    int sum = 0;

    if (argc > 1) {
        show_str(argv[1]);
    }

    for (i = 0; i < MAX_CNT; i++) {
        sum += i;
    }

    printf("sum:%d\n", sum);

    return 0;
}
$ gdb a.out 
(gdb) r hello
Starting program: /home/zorro/voip/Shengy-st/linux-c-demo/041-2-gdb-set-arg/a.out hello
str: [hello]
sum:10
[Inferior 1 (process 25391) exited normally]
(gdb) set args world
(gdb) r
Starting program: /home/zorro/voip/Shengy-st/linux-c-demo/041-2-gdb-set-arg/a.out world
str: [world]
sum:10
[Inferior 1 (process 25395) exited normally]
(gdb) 

4.17 core调试

core文件是程序内存越界时程序转储的程序内存信息的文件,可以看到函数调用栈等信息,用来分析程序异常退出的原因。
源码:
hello_world_main.c:

#include <stdio.h>

int show_str(char *str)
{
    int *p = NULL;

    *p = 20;
    printf("str: [%s]\n", str);

    return 0;
}

int main(int argc, char *argv[])
{

    show_str("hello world");

    return 0;
}

想要生成core文件,需要通过ulimit设置core文件的最大大小,可以设置为无限(unlimited)

$ 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) 7867
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) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7867
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
$ ulimit -c unlimited
$ ulimit -c
unlimited
$ ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
$ ls core
core

以下示例是通过gdb查看core文件信息,可以发现指针p是空指针

$ gdb a.out core 
Reading symbols from a.out...done.
[New LWP 25544]
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000000000400545 in show_str (str=0x40061f "hello world") at hello_world_main.c:8
8	    *p = 20;
(gdb) p p
$1 = (int *) 0x0
(gdb)

五、关键说明

  • 为了防止代码泄密,一般正式发布的程序不会带上-g选项进行编译
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浪游东戴河

你就是这个世界的唯一

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值