gdb 调试

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了gdb 调试相关的知识,希望对你有一定的参考价值。

Gdb调试

在Linux下进行C++程序的调试,其中gdb是非常强大的工具,不再使用LOG_INFO这种使用输出来观察数据的正确性,及如何面对段错误,这种非常难以定位的问题,在gdb中都能够给予非常好的支持,其具体使用方法如下:

1.             设置断点

整个程序如下:

#include <stdio.h>

int nGlobalVar = 0;

int tempFunction(int a, int b)

{

    printf("tempFunction is called, a = %d, b = %d \n", a, b);

    return (a + b);

}

 

int main()

{

    int n;

    n = 1;

    n++;

    n--;

    nGlobalVar += 100;

    nGlobalVar -= 12;

    printf("n = %d, nGlobalVar = %d \n", n, nGlobalVar);

    n = tempFunction(1, 2);

    int i=0;

    for(;i<10;++i)

    {

        printf("data is %d\n",i);

    }

    printf("n = %d\n", n);

    return 0;

}

  

1)        Break

断点位置的设置,可以包括行号、函数:

指定的行号 :b 12

指定的文件行号:b test:12

指定的函数:b fun

指定文件的函数:b test:fun

根据条件设置断点:b 21 if i==5

Breakpoint 1 at 0x4008b6: file /root/project/monitor_center/dbhelper_server/Debug/Test/Gdb_Test/swap_1.cc, line 21.

(gdb) r

Starting program: /root/project/monitor_center/dbhelper_server/Debug/Test/Gdb_Test/bin/gdb_test

n = 1, nGlobalVar = 88

tempFunction is called, a = 1, b = 2

data is 0

data is 1

data is 2

data is 3

data is 4

在i为5的时候程序停止

 

2)        Watch 观察点

  1. 设置断点之后,b 18 使得程序可以在18行:Int i=0;处停止
  2. r 命令,让程序再18行停止
  3. watch i设置观察点
  4. 使用c(ontinue)观察设置的观察点是否有变化

得到的结果为:

Breakpoint 2, main () at /root/project/monitor_center/dbhelper_server/Debug/Test/Gdb_Test/swap_1.cc:18

18         int i=0;

(gdb) watch i

Hardware watchpoint 4: i

(gdb) c

Continuing.

data is 0

Hardware watchpoint 4: i

 

Old value = 0

New value = 1

0x00000000004008ce in main () at /root/project/monitor_center/dbhelper_server/Debug/Test/Gdb_Test/swap_1.cc:19

19         for(;i<10;++i)

可以看到变量发生变化前后的值。

3)        tbreak

与Break之间的区别在于它是一个temp的断点,运行一次之后该断点将会被删除。

2.             打印数据

  1. 打印变量的值: p n
  2. 打印变量地址:p &n
  3. 查看当前运行的行及文件:backtrace,可以简写为bt。

如果要调试一个core文件,当程序奔溃之后生成一个core文件,然后直接定位到发生程序奔溃的位置,可以采用:ulimit -c unlimited生成core文件。

问题:对core文件如何的调试?

在gdb 命令中使用:gdb core文件

  1. 以不同的进制显示变量值:p /x var (使用16进制显示变量),其中d为10进制,f为浮点型,t为二进制格式
  2. 显示变量的类型,whatis a

whatis i

type = int

添加一个结构体,在main中添加一个类变量  TestA _test A;

class testA

{

  public:

    int a;

    int b;

    TestA()

    {

        a = 2;

        b = 5;

    }

};

设置断点:b 29,r运行,p _testA,得到:

$6 = {a = -7296, b = 32767}

执行whatis _testA,得到:

type=TestA

想要更详细的信息:ptype _testA,结果为:

type = class TestA {

  public:

    int a;

    int b;

    TestA(void);

}

 

可以观察到,在每个print后面都会给输出的变量加一个变量标号,所以,可以使用该标记输出,而不同输出冗长的变量名,比如:

(gdb) p nGlobalVar

$1 = 88

(gdb) p $1

$2 = 88

  1. 显示调用函数值

print tempFunction(2,3)将得到5

  1. 查看文件中的变量:p ‘tets.c’::n,
  2. 查看函数中的变量: 使用作用域,如果是与全局的变量发生冲突的时候
  3. 显示数组:p *[email protected]
  4. 设置参数值:set variable n=13
  5. 立即执行完当前的函数:直接使用finish,将跳出当前的函数。
  6. 执行完当前的循环:until 循环外面的行号,然后c,将会达到循环外面。比如设置until 到下面这行,代码将直接跳出循环。

3.             设置

4.             执行代码

printf("n = %d\n", n);

  1. 程序继续运行直到遇到断点或者程序结束:c
  2. 下一条语句:n(ext),step over
  3. 下一步:s(tep), step in
  4. 运行:r,继续往下运行,直到一个断点停下来
  5. 调用程序中的函数:call tempFunction(3,7)
  6. 列出所有的断点:info b
  7. 列出某个断点:info break的断点号
  8. 列出函数 list tempFunction(int,int)
  9. List 默认显示10行
  10. List 0,20 列出0-20行之间的源码
  11. 删除断点,由于gdb会给每个断点设置一个序号,所以,可以利用这个序号删除指定的断点,比如我们列出info b得到下面的结果:

5.             列出所有的断点

6.             列出源代码

7.             删除断点

Num     Type           Disp Enb Address            What

1 breakpoint     keep y   0x0000000000400854 in main() at /root/project/monitor_center/dbhelper_server/Debug/Test/Gdb_Test/swap_1.cc:14

         breakpoint already hit 1 time

2 breakpoint     keep y   0x00000000004008b6 in main() at /root/project/monitor_center/dbhelper_server/Debug/Test/Gdb_Test/swap_1.cc:26

         stop only if i==4

3   breakpoint     keep y   <PENDING>          i==5

4 breakpoint     keep y   0x00000000004008b6 in main() at /root/project/monitor_center/dbhelper_server/Debug/Test/Gdb_Test/swap_1.cc:26

         stop only if i==5

  1. 对断点3进行删除:delete 3

再次执行info b之后,该断点已经被删除,但是后面的断点的序号并不会发生改变,整个断点的序号变为:1,2,4

  1. 删除一个连续的断点,使用断点号来描述,比如,删除1-2号断点,得到结果为:

(gdb) delete 1-2

(gdb) info b

Num     Type           Disp Enb Address            What

4 breakpoint     keep y   0x00000000004008b6 in main() at /root/project/monitor_center/dbhelper_server/Debug/Test/Gdb_Test/swap_1.cc:26

         stop only if i==5

可以看到只有4号断点了

  1. 删除某个函数内的所有断点:clear fun
  2. 删除某个文件中的所有断点:clear test.c
  3. 删除文件中的某个函数的断点:clear test.c:fun
  4. 删除行号的断点:clear 行号,注意:可能在某种情况下我们会在同一行设置多个断点,但是这些断点也许不是连续的,如果使用delete,会显得有点麻烦,利用clear命令会将该行中所有的断点都删除。
  5. 删除某文件中行号的所有断点:clear test.c:行号
  6. 是否有删除所有的断点,其命令为:delete ,后面不带任何的参数,在执行之后会询问是否删除所有的断点。
  7. 显示在当前文件中包含text串的下一行:Search text
  8. 显示包含text的前一行:reverse-search text

8.             查找文本

9.             其它辅助

1.  列出当前的目录:pwd

2.  改变运行的目录:cd

3.  Info program 查看程序是否在运行

以上是关于gdb 调试的主要内容,如果未能解决你的问题,请参考以下文章

代码调试篇:gdb调试快速入门指南

GDB代码调试与使用

GDB调试

使用GNU/gdb调试Linux C/C++可执行程序查看出错源代码、设置断点

代码调试工具GDB

代码调试篇:如何编写 gdb 自定义命令