gdb的基本调试方法

1.怎么调试程序

在linux下,我们通常用gcc来编译链接程序,用gdb来调试程序。在用gcc生成程序的时候,用-g选项来使程序可以调试:

[email protected]:~/gdb$ gcc -g -Wall gdbtest.c -o gdbtest

然后在用如下命令调试程序:

[email protected]:~/gdb$ gdb gdbtest

2.gdb的基本命令介绍

run 在gdb中运行你的程序,一般会在你设置的断点地方停止。
start 也是在gdb中运行程序,不过默认实在程序的main函数停止。
break 用break命令在程序中来设置断点,方便程序的调试。
continue continue继续执行程序,直到遇到下一个断点。
step step单步调试程序,遇到有函数调用的地方,会跳进该函数,继续单步调试。
next next也是单步调试程序,但是在函数的调用的地方,不会跳进该函数,二回继续执行。
list list列出当前的源代码,如果参数是函数名,就会列出该函数的定义。
print 用来打印变量。
display 用来显示变量的。
backtrace 用来显示函数的调用栈。

3.设置断点的基本方法

break linenumber
b
linenumber
在当前文件的第linenumber行设置一个断点。
break functionname
b
functionname
在当前文件的functionname函数设置一个断点
break filename:linenumber
b
filename:linenumber
在filename文件第linenumber行设置一个断点。
break filename:functionname
b
filename:functionname
在filename文件的functionname函数设置一个断点。

(gdb) l
        38        int x = atoi(argv[1]);
       
39        int y = atoi(argv[3]);
        40        printf("x = %d, y =
%d.\n", x , y);
        41   
        42        if (0 == strcmp("+",
argv[2])) {
        43            int result = add(x, y);
       
44            printf("%s %s %s = %d.\n", argv[1], argv[2], argv[3],
result);
        45        }
        46   
        47        if (0 ==
strcmp("-", argv[2])) {

在43的一行设置一个断点:

(gdb) b
43
            Breakpoint 2 at 0x80485dc: file gdbtest.c,
line 43.

在add函数设置一个断点:

(gdb) b
add
            Breakpoint 3 at 0x8048500: file gdbtest.c,
line 7.

在sub函数设置一个断点:

(gdb) b
sub
            Breakpoint 4 at 0x804850d: file gdbtest.c,
line 12.

在div函数设置一个断点:

(gdb) b
div
            Breakpoint 5 at 0xb7e487e0: file div.c, line
56.

用info break(i   b)查看当前设置的断点信息:

(gdb) info
break
            Num     Type           Disp Enb Address   
What
            2       breakpoint     keep y   0x080485dc in main at
gdbtest.c:43
            3       breakpoint     keep y   0x08048500 in add at
gdbtest.c:7
            4       breakpoint     keep y   0x0804850d in sub at
gdbtest.c:12
            5       breakpoint     keep y   0xb7e487e0 in div at
div.c:56

用delete删除设置的断点(删除断点的方法设置的时候都差不多):

(gdb) delete
5
(gdb) i
b
            Num     Type           Disp Enb Address   
What
            2       breakpoint     keep y   0x080485dc in main at
gdbtest.c:43
            3       breakpoint     keep y   0x08048500 in add at
gdbtest.c:7
            4       breakpoint     keep y   0x0804850d in sub at
gdbtest.c:12

第5个断点没有了。

直接用delete删除所有设置的断点:

(gdb) delete
            删除所有断点吗? (y or n)
n

disable命令使某个断点失效:

(gdb) disable
3

(gdb) i
b
            Num     Type           Disp Enb Address   
What
            2       breakpoint     keep y   0x080485dc in main at
gdbtest.c:43
            3       breakpoint     keep n   0x08048500 in add at gdbtest.c:7
            4      
breakpoint     keep y   0x0804850d in sub at gdbtest.c:12

enable命令是某个断点有效:

(gdb) enable
3
(gdb) i
b
            Num     Type           Disp Enb Address   
What
            2       breakpoint     keep y   0x080485dc in main at
gdbtest.c:43
            3       breakpoint     keep
y   0x08048500 in add at gdbtest.c:7
            4      
breakpoint     keep y   0x0804850d in sub at gdbtest.c:12

只执行disable命令就是让所有断点失效:

(gdb) disable
(gdb) i b
            Num     Type          
Disp Enb Address    What
            2       breakpoint     keep n   0x080485dc in main at gdbtest.c:43
           
3       breakpoint     keep n   0x08048500 in add at
gdbtest.c:7
            4       breakpoint     keep n   0x0804850d in sub at gdbtest.c:12

只执行enable命令就是让所有断点有效:

(gdb) enable
(gdb) i b
            Num     Type          
Disp Enb Address    What
            2       breakpoint     keep y   0x080485dc in main at gdbtest.c:43
           
3       breakpoint     keep y   0x08048500 in add at
gdbtest.c:7
            4       breakpoint     keep y   0x0804850d in sub at gdbtest.c:12

4.gdb打印变量

在gdb可以用print/p命令来打印变量,打印的方式可以分为以下几种:

x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型
o 按八进制格式显示变量
t 按二进制格式显示变量
a 按十六进制格式显示变量
c 按字符格式显示变量
f 按浮点数格式显示变量

(gdb) l
            1    #include
<stdio.h>
            2   
            3    int
main(void)
            4    {
            5        char
a[100];
            6        int i;
            7   
           
8        for (i = 0; i < 100; i++) {
            9        a[i] =
i;
            10      }

11     return 0;

12  }

(gdb) start
            Temporary breakpoint
1 at 0x8048447: file print.c, line 4.
            Starting program:
/home/test/gdb/print

Temporary breakpoint 1, main () at
print.c:4
             4    {

(gdb) u
11
            main () at print.c:12
            12       
return 0;

以十六进制打印数组a的内容,会显示很多:

(gdb) p/x
a
             $1 = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18,
               0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
0x2d, 0x2e, 0x2f,
               0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43,
0x44, 0x45, 0x46,
               0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d,
0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
0x5b, 0x5c, 0x5d,
               0x5e, 0x5f, 0x60, 0x61, 0x62,
0x63}

可以用p *[email protected] count打印数组array_name的前count个元素。

以十六进制指定打印数组的前面十个元素:

(gdb) p/x
*[email protected]
              $2 = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6,
0x7, 0x8, 0x9}

在c语言中经常有很多struct自定义变量,在程序的执行的可以通过whatis命令和ptype这俩个命令来查看变量类型。

(gdb) l
-15
1    #include <stdio.h>
2   
3    typedef
struct listnode
4    {
5        int value;
6        struct listnode
*next;
7    }Node;
8   
9    Node node1 = {1, NULL};
10

(gdb) start
    Temporary breakpoint 1 at
0x80483f3: file struct.c, line 13.
    Starting program:
/home/test/gdb/struct

Temporary breakpoint 1, main () at struct.c:13
   
13        Node node2 = {2, NULL};
(gdb) n
    15        return
0;

查看node1的变量类型,没有到结构体,只显示类型:

(gdb) whatis
node1
             type = Node

查看node2的变量类型,看到结构体里面都有些什么:

(gdb) ptype
node2
             type = struct listnode
{
                      int value;
                      struct listnode
*next;
            }

gdb中使用“x”命令来打印内存的值,格式为“x/nfu
addr
”。含义为以f格式打印从addr开始的n个长度单元为u的内存值。参数具体含义如下:
a)n:输出单元的个数。
b)f:是输出格式。比如x是以16进制形式输出,o是以8进制形式输出,等等。
c)u:标明一个单元的长度。b是一个byteh是两个byte(halfword),w是四个byte(word),g是八个byte(giant
word)。

(gdb) l
    1    #include
<stdio.h>
    2   
    3    int main(void)
    4    {
   
5        char a[100];
    6        int i;
    7   
    8        for (i
= 0; i < 100; i++) {
    9        a[i] = i;
    10        }
   
(gdb) start
    Temporary breakpoint 1 at
0x8048447: file print.c, line 4.
    Starting program: /home/test/gdb/print

Temporary breakpoint 1, main () at print.c:4
    4   
{
(gdb) n
        8        for (i = 0; i <
100; i++) {
(gdb) n
        9        a[i] = i;
(gdb)
n
       
8        for (i = 0; i < 100; i++) {
(gdb) u 11
        main () at
print.c:12
        12        return 0;

以16进制格式打印数组前a16个byte的值:

(gdb) x/16xb
a
        0xbfffedf8:    0x00    0x01    0x02    0x03   
0x04    0x05    0x06    0x07
        0xbfffee00:    0x08    0x09    0x0a   
0x0b    0x0c    0x0d    0x0e    0x0f

以无符号10进制格式打印数组a前16个byte的值:

(gdb) x/16ub
a
        0xbfffedf8:    0    1    2    3    4    5    6   
7
        0xbfffee00:    8    9    10    11    12    13    14   
15

以16进制格式打印数组a前16个word(4个byte)的值:

(gdb)
x/16xw a
        0xbfffedf8:   
0x03020100    0x07060504    0x0b0a0908    0x0f0e0d0c
        0xbfffee08:   
0x13121110    0x17161514    0x1b1a1918    0x1f1e1d1c
        0xbfffee18:   
0x23222120    0x27262524    0x2b2a2928    0x2f2e2d2c
        0xbfffee28:   
0x33323130    0x37363534    0x3b3a3938

时间: 2024-10-21 21:20:23

gdb的基本调试方法的相关文章

Linux内核调试方法总结之ptrace

ptrace [用途] 进程跟踪器,类似于gdb watch的调试方法 [原理][详细说明参考man ptrace帮助文档] ptrace系统调用主要是父进程用来观察和控制子进程的执行过程.检查并替换子进程执行序列或者寄存器值的一种手段.主要用于实现断点调试和跟踪系统调用. [接口说明] #include <sys/ptrace.h> long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data); 序

GDB调试方法精粹

http://blog.chinaunix.net/uid-26000296-id-3499802.html 一.多线程调试1. 多线程调试,最重要的几个命令:info threads                        查看当前进程的线程.                                          GDB会为每个线程分配一个ID, 后面操作线程的时候会用到这个ID.                                          前面有*的是

GDB中应该知道的几个调试方法

七.八年前写过一篇<用GDB调试程序>,于是,从那以后,很多朋友在MSN上以及给我发邮件询问我关于GDB的问题,一直到今天,还有人在问GDB的相关问题.这么多年来,有一些问题是大家反复在问的,一方面,我觉得我以前的文章可能没有说清楚,另一方面,我觉得大家常问的问题正是最有用的,所以,在这里罗列出来.希望大家补充. 一.多线程调试多线程调试可能是问得最多的.其实,重要就是下面几个命令: info thread 查看当前进程的线程.thread <ID> 切换调试的线程为指定ID的线程

GDB中应该知道的几个调试方法 来自陈皓

GDB中应该知道的几个调试方法 2011年2月10日陈皓发表评论阅读评论62,325 人阅读 七.八年前写过一篇<用GDB调试程序>,于是,从那以后,很多朋友在MSN上以及给我发邮件询问我关于GDB的问题,一直到今天,还有人在问GDB的相关问题.这么多年来,有一些问题是大家反复在问的,一方面,我觉得我以前的文章可能没有说清楚,另一方面,我觉得大家常问的问题正是最有用的,所以,在这里罗列出来.希望大家补充. 一.多线程调试 多线程调试可能是问得最多的.其实,重要就是下面几个命令: info th

linux 下C/C++程序常用调试方法(gdb)

 不管是在开发或者运行过程中,调试保证程序正常运行最基本的手段,熟悉这些调试方式,方便我们更快的定位程序问题所在,提高开发效率. 一 程序正常运行调试 (1)  直接使用gdb 开发过程中最常用的方式,我们可以在其过程中给程序添加断点,监视等辅助手段,监控其行为是否与我们设计相符,比如: (2)      程序已经运行,通过attach附加到进程 二 程序中断后调试 首先简单介绍下linux 下的信号: 软中断信号(signal,又简称为信号)用来通知进程发生了异步事件.进程之间可以互相通过

【转】GDB中应该知道的几个调试方法

文章来源:http://coolshell.cn/articles/3643.html GDB中应该知道的几个调试方法 2011年02月10日 陈皓 评论 40 条评论  70,776 人阅读 七.八年前写过一篇<用GDB调试程序>,于是,从那以后,很多朋友在MSN上以及给我发邮件询问我关于GDB的问题,一直到今天,还有人在问GDB的相关问题.这么多年来,有一些问题是大家反复在问的,一方面,我觉得我以前的文章可能没有说清楚,另一方面,我觉得大家常问的问题正是最有用的,所以,在这里罗列出来.希望

Linux学习——Gdb基本调试方法&amp;&amp;多线程调试

1.Gdb的基本调试 示例代码 //e.c #include <stdio.h> void debug(char *str) { printf("debug info :%s\n",str ); } int main(int argc,char *argv[]){ int i,j; j=0; for(i=0;i<10;i++){ j+=5; printf("now a=%d\n", j); } } 1 2 3 4 5 6 7 8 9 10 11 1

gdb 和 addr2line 调试 crash(包含如何调试so里面的crash)

嵌入式编程中会遇到各种crash的问题. 对于这样的问题,有两种调试方法: addr2line  和 gdb. 第一章   先讲解下gcc 编译加不加 -g 对程序的影响, 还有strip. //1.1.cpp #include <iostream> using namespace std; bool IsUnique() {         int k = 0, m = 0;         k = k/m;      //这里会crash         return true; } in

python 调试方法

一.使用pdb http://blog.csdn.net/wyb_009/article/details/8896744   二.使用gdb 需首先配置gdb pythin支持,步骤如下: 1.修改Python-2.6/Misc/gdbinit,将 while $_i < f->f_nlocals 修改为 while $_i < f->f_code->co_nlocals 2.在文件:~/.gdbinit中,加入如下内容 source Python-2.6/Misc/gdbi