Linux之GDB调试介绍与应用20170601

一、GDB调试命令


 


描述


backtrace(或bt)


查看各级函数调用及参数


finish


连续运行到当前函数返回为止,然后停下来等待命令


frame(或f) 帧编号


选择栈帧


info(或i) locals


查看当前栈帧局部变量的值


list(或l)


列出源代码,接着上次的位置往下列,每次列10行


list 行号


列出从第几行开始的源代码


list 函数名


列出某个函数的源代码


next(或n)


执行下一行语句


print(或p)


打印表达式的值,通过表达式可以修改变量的值或者调用函数


quit(或q)


退出gdb调试环境


set var


修改变量的值


start


开始执行程序,停在main函数第一行语句前面等待命令


step(或s)


执行下一行语句,如果有函数调用则进入到函数中

比如还有几个命令如下

wath     观察一个变量

current 跳转到下个断点,或则跳转到观察点

quit  退出gdb调试

安装GDB:

  1. sudo apt-get install gdb

二、分析例子

代码如下:

  1. #include <stdio.h>
  2. int add_range(int low, int high);
  3. int add (int a, int b);
  4. int add (int a, int b) {
  5. int result = a + b;
  6. return result;
  7. }
  8. int add_range(int low, int high)
  9. {
  10. int i = 0, sum = 0;
  11. for (i = low; i <= high; i++)
  12. sum = sum + i;
  13. return sum;
  14. }
  15. int main(void)
  16. {
  17. int result[100];
  18. result[0] = add_range(1, 10);
  19. result[1] = add_range(1, 100);
  20. printf("result[0]=%d\nresult[1]=%d\n", result[0], result[1]);
  21. int a = 9, b = 10;
  22. int result1 = a + b;
  23. int result2 = a * b;
  24. printf("result1 = %d, result2 = %d", result1, result2);
  25. int result3 = add(result1, result2) ;
  26. printf("result3=%d", result3);
  27. if (result3 == 10) {
  28. printf("result3 = %d", result3);
  29. } else {
  30. printf("result != 10");
  31. }
  32. return 0;
  33. }

1.在编译时要加上-g选项,生成的可执行文件才能用gdb进行源码级调试:

命令如下:

  1. gcc -g main.c -o hello1
  2. gdb hello1

如下图

2.然后我们怎么查看源代码呢?命令如下

  1. list

然后我们还要看下面的代码可以怎么样操作,你可以  回车 或则 输入l  之后回车(因为list 简写 l)注意很多gdb命令都可以简写成首字母,或则输入 list 2 回车也可以

我们退出gdb命令如下

  1. quit

我们这里先不退出

3.我们先运行程序用下面命令

  1. start

如下图

4.我们用next命令执行下一条语句,next命令简写为n,输入下民命令

  1. n

5.我们也可是使用step命令进入函数内入跟踪,简写命令s,再输入命令n执行下一步,输入下面命令

  1. s

6.在函数中有几种查看状态的办法,backtrace命令(简写为bt)可以查看函数调用的栈帧:

可见当前的add_range函数是被main函数调用的,main传进来的参数是low=1, high=100main函数的栈帧编号为1,add_range的栈帧编号为0。

7.现在可以用info命令(简写为i)查看函数局部变量的值:

i locals

add_range函数局部变量的值:

v:shapes="_x0000_i1032">

如果想查看main函数当前局部变量的值也可以做到,先用frame命令(简写为f)选择1号栈帧然后再查看局部变量:

(gdb) f 1

输入下面命令

  1. i locals

8.我们还可以用p打印出当前值

9.我们也可以修改sum的值

  1. set var sum = 0

v:shapes="_x0000_i1036">

10.比如我们不要运行这个函数了,要运行这个函数下面的程序,我们可以用finish

  1. finish

11.quit    
退出命令

v:shapes="_x0000_i1038">

三、断点调试

举例分析:

hello2.c源文件如下

  1. #include<stdio.h>
  2. int main() {
  3. int a = 1, b = 2, c = 3;
  4. int i;
  5. printf("hello chenyu");
  6. for (i = 0 ; i < 100; i++) {
  7. ++a;
  8. if (i > 90) {
  9. ++b;
  10. } else {
  11. ++c;
  12. }
  13. }
  14. printf("a = %d, b = %d, c = %d", a, b, c);
  15. int cc = 0;
  16. for (cc; cc < 9; cc++) {
  17. printf("c %d", i);
  18. }
  19. return 0;
  20. }

比如我们在 ++b (第10行)这行和printf("c %d", i)(第18行)这两行打断点示例:

1、编译

---在编译时要加上-g选项,生成的可执行文件才能用gdb进行源码级调试

gcc -g hello2.c

2、gdb调试

  1. gdb hello2

3、显示代码行数命令如下

  1. list

list(或l)


列出源代码,接着上次的位置往下列,每次列10行


list 行号


列出从第几行开始的源代码


list 函数名


列出某个函数的源代码

回车 往下查看

4 、然后输入打断点命令

1) 、源文件的某一行设置断点

  1. break 行号

2)、一个特定的函数设置断点

  1. break 函数名

3)、设置条件断点

  1. break 行号 if 条件

示例:

  1. break 10
  2. break 18

图片如下:

5 、 运行并且跳转到断点

1)、运行

  1. start

2) 、跳转到断点命令(countine 简写c)

  1. c

程序就到++b 这行来,上面2个步骤也可以用这个run (简写 r)命令代码

  1. r

我们这里代码会跳到这个断点里面来,我么就避免了手动循环这么多次,因为这个断点会打很多次,所以我们可以用c命令,还是会在这行,所以打断点一般不要打在循环里面,当这个代码执行完之后,我们再用c命令,就会打印18行的代码

6、我们也可以用watch命令来观察变量,如果变量的值发生变化,程序就会停止

  1. watch b

7、看函数局部变量的值或单个变量的值可以用下面命令

  1. i locals
  2. p c

如果想查看其他函数当前局部变量的值也可以做到,先用frame命令(简写为f)选择其他函数的栈帧号(backtrace命令(简写为bt)获取)然后再查看局部变量

f 1

i locals

8、进入函数内部用下面命令

  1. s

9、单步调试往下执行用下面命令

  1. n

10、删除断点

  1. delete 行号

11、退出gdb命令

  1. quit

四、如何保存断点

有时候运行时,上次打的断点没了,怎么保存呢?

1、查看断点信息并保存

  1. info b

2
、保存断点

  1. save breakpoint fig.dp

断点保存在fig.dp文件里面

3、调试时候读取保存断点文件

  1. gdb hello2 -x fig.dp

要记住加上参数 -x

然后再去查看是否有断点

  1. info b

可以看到是有2个断点的

原文:http://blog.csdn.net/u011068702/article/details/53925415

   http://blog.csdn.net/u011068702/article/details/53931648

五、实例:

示例1:

[email protected]:/work/projects/test$ gcc -o
LinkListClearOprNoHeadNode -g LinkListClearOprNoHeadNode.c

boo[email protected]:/work/projects/test$ gcc -g -o
LinkListClearOprNoHeadNode LinkListClearOprNoHeadNode.c

[email protected]:/work/projects/test$ gdb
LinkListClearOprNoHeadNode

GNU gdb (GDB)
7.0-ubuntu

Copyright (C) 2009 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 "i486-linux-gnu".

For bug reporting instructions, please see:

<http://www.gnu.org/software/gdb/bugs/>...

Reading symbols from /work/projects/test/LinkListClearOprNoHeadNode...done.

(gdb) list

35     
-Input                  :

36     
-Output                 :

37     
-Return                 :

38      * Modify Date     Version                Author                   Modification

39      *
-----------------------------------------------

40      *
2017/03/29      V1.0.0                 Yu Weifeng       Created

41     
******************************************************************************/

42      int main(int argc,char **argv)

43      {

44              PT_LinkList ptLinkListHead=NULL;

(gdb)

45              T_LinkListElement
tLinkListElement;

46              tLinkListElement.cData=1;

47             
InsertNodeToLinkList(&ptLinkListHead,1,&tLinkListElement);

48              tLinkListElement.cData=23;

49             
InsertNodeToLinkList(&ptLinkListHead,2,&tLinkListElement);

50              tLinkListElement.cData=24;

51             
InsertNodeToLinkList(&ptLinkListHead,3,&tLinkListElement);

52              tLinkListElement.cData=26;

53             
InsertNodeToLinkList(&ptLinkListHead,4,&tLinkListElement);

54              tLinkListElement.cData=66;

(gdb)

55             
InsertNodeToLinkList(&ptLinkListHead,5,&tLinkListElement);

56              tLinkListElement.cData=99;

57              InsertNodeToLinkList(&ptLinkListHead,6,&tLinkListElement);

58

59              printf("插入结果:");

60              TraverseLinkList(ptLinkListHead);

61             
DeleteNodeFromLinkList(ptLinkListHead,6,&tLinkListElement);

62              DeleteNodeFromLinkList(ptLinkListHead,4,&tLinkListElement);

63

64              printf("删除结果:");

(gdb)

65              TraverseLinkList(ptLinkListHead);

66

67              printf("插入结果:");

68              tLinkListElement.cData=5;

69              InsertNodeToLinkList(&ptLinkListHead,3,&tLinkListElement);

70              TraverseLinkList(ptLinkListHead);

71              return 0;

72      }

73     
/*****************************************************************************

74     
-Fuction                :
GetLinkListLength

(gdb) info b

No breakpoints or watchpoints.

(gdb) break 47

Breakpoint 1 at 0x80484ca: file
LinkListClearOprNoHeadNode.c, line 47.

(gdb) start

Temporary breakpoint 2 at 0x80484bd: file
LinkListClearOprNoHeadNode.c, line 44.

Starting program: /work/projects/test/LinkListClearOprNoHeadNode

Temporary breakpoint 2, main (argc=1, argv=0xbffff784)
at LinkListClearOprNoHeadNode.c:44

44             
PT_LinkList ptLinkListHead=NULL;

(gdb) c

Continuing.

Breakpoint 1, main (argc=1, argv=0xbffff784) at LinkListClearOprNoHeadNode.c:47

47             
InsertNodeToLinkList(&ptLinkListHead,1,&tLinkListElement);

(gdb) s

InsertNodeToLinkList (i_pptLinkListHead=0xbffff6c8,
i_dwPosition=1, i_ptElement=0xbffff6cf) at LinkListClearOprNoHeadNode.c:114

114             int ret=-1;

(gdb) i locals

ret = 134513528

ptLinkListNode = 0xbffff6a8

ptInsertListNode = 0x8049ff4

iLen = 2424820

(gdb) p iLen

$1 = 2424820

(gdb) n

115             T_LinkList
*ptLinkListNode=*i_pptLinkListHead;

(gdb)

116             T_LinkList *ptInsertListNode=NULL;

(gdb)

117             int iLen=0;

(gdb)

118            
iLen=GetLinkListLength(ptLinkListNode);

示例2:

[email protected]:/work/projects/test$
gdb LinkListClearOprNoHeadNode

GNU gdb (GDB)
7.0-ubuntu

Copyright (C) 2009
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 "i486-linux-gnu".

For bug reporting
instructions, please see:

<http://www.gnu.org/software/gdb/bugs/>...

Reading symbols from
/work/projects/test/LinkListClearOprNoHeadNode...done.

(gdb) list
InsertNodeToLinkList

108     * Modify Date     Version                Author                   Modification

109     * -----------------------------------------------

110     * 2017/03/29      V1.0.0                 Yu Weifeng       Created

111    
******************************************************************************/

112     static int InsertNodeToLinkList(T_LinkList
**i_pptLinkListHead,int i_dwPosition,T_LinkListElement *i_ptElement)

113     {

114             int ret=-1;

115             T_LinkList
*ptLinkListNode=*i_pptLinkListHead;

116             T_LinkList *ptInsertListNode=NULL;

117             int iLen=0;

(gdb)

118            
iLen=GetLinkListLength(ptLinkListNode);

119            
if(i_dwPosition<1||i_dwPosition-1>iLen)

120             {

121                     ret=-1;

122                    
printf("InsertPositionErr,Len:%d,Pos:%d\r\n",iLen,i_dwPosition);

123             }

124             else

125             {

126                    
ptInsertListNode=(T_LinkList *)malloc(sizeof(T_LinkList));

127                     if(NULL==ptInsertListNode)

(gdb)

128                     {

129                             printf("pInsertListNodeMallocErr\r\n");

130                             ret=-1;

131                     }

132                     else

133                     {

134                            
ptInsertListNode->ptNext=NULL;

135                             memcpy(&ptInsertListNode->tData,i_ptElement,sizeof(T_LinkListElement));

136                            
if(NULL==*i_pptLinkListHead)

137                             {

(gdb)

138                                    
*i_pptLinkListHead=ptInsertListNode;

139                             }

140                             else

141                             {

142                                    
while(--i_dwPosition)

143                                     {

144                                            
ptLinkListNode=ptLinkListNode->ptNext;

145                                     }

146                                    
ptInsertListNode->ptNext=ptLinkListNode;

147                                     ptLinkListNode=ptInsertListNode;

(gdb) info b

No breakpoints or
watchpoints.

(gdb) break 144

Breakpoint 1 at
0x804873f: file LinkListClearOprNoHeadNode.c, line 144.

(gdb) start

Temporary breakpoint 2
at 0x80484bd: file LinkListClearOprNoHeadNode.c, line 44.

Starting program:
/work/projects/test/LinkListClearOprNoHeadNode

Temporary breakpoint
2, main (argc=1, argv=0xbffff784) at LinkListClearOprNoHeadNode.c:44

44              PT_LinkList ptLinkListHead=NULL;

(gdb) c

Continuing.

ListNull

Breakpoint 1,
InsertNodeToLinkList (i_pptLinkListHead=0xbffff6c8, i_dwPosition=1,
i_ptElement=0xbffff6cf) at LinkListClearOprNoHeadNode.c:144

144                                            
ptLinkListNode=ptLinkListNode->ptNext;

(gdb) i locals

ret = -1

ptLinkListNode =
0x804b008

ptInsertListNode =
0x804b018

iLen = 1

时间: 2024-09-28 19:55:58

Linux之GDB调试介绍与应用20170601的相关文章

Linux知识(5)----LINUX下GDB调试

参考资料: 1.LINUX下GDB调试

Linux下gdb调试

关于gdb的其他客套话不多说,直接进入正题. 一.gdb基本命令列表: 命令 解释 简写 file 装入想要调试的可执行文件 无 list 列出产生执行文件源代码的一部分 l next 执行一行源代码但不进入函数内部 n step 执行一行源代码而且进入函数内部 s run 执行当前被调试的程序 r continue 继续执行程序 c quit 终止gdb q print 输出当前指定变量的值 p break 在代码里设置断点 b info break 查看设置断点的信息 ib delete 删

【转】linux下gdb调试

本文写给主要工作在Windows操作系统下而又需要开发一些跨平台软件的程序员朋友,以及程序爱好者. GDB中的命令固然很多,但我们只需掌握其中十个左右的命令,就大致可以完成日常的基本程序调试工作. 命令 解释 示例 file <文件名> 加载被调试的可执行程序文件. 因为一般都在被调试程序所在目录下执行GDB,因而文本名不需要带路径. (gdb) file gdb-sample r Run的简写,运行被调试的程序. 如果此前没有下过断点,则执行完整个程序:如果有断点,则程序暂停在第一个可用断点

Linux下GDB调试C/C++

首先先编译程序并生成调试符号: gcc -g -c main.cpp gcc -o exefile main.o 以上的exefile为可执行程序的文件名 然后: gdb exefile 可以开始gdb调试了. 然后在(gdb)那里写入l命令,列出程序源码清单,再次回车是往下列出. (gdb)break linenum 是在代码行号处下断点. 然后(gdb) r 是运行调试程序,r当然就是run的意思 (gdb) n 就是next的意思,单步调试 (gdb) c 就是continue的意思,意味

Linux下gdb调试(tui)

1 处于TUI模式的GDB 为了以TUI模式运行GDB,可以在调用GDB时在命令行上指定-tui选项,或者处于非TUI模式时在GDB中使用Ctrl+X+A组合键.如果当前处于TUI模式,后一种命令方式就会使你离开TUI模式. 在TUI模式中,GDB窗口划分为两个子窗口——一个用于输入GDB命令,而另一个用于查看源代码. 例如: 源代码为ins.c #include <stdio.h> int x[10], y[10], num_inputs, num_y = 0; void get_args(

【linux】gdb调试

设要调试的文件是 bug.c 先用 gcc -o bug -ggdb bug.c 生成可执行文件 输入 gdb bug  //bug是待调试的可执行文件的名字 输入 list(简写为l)  可查看源代码 输入 run(简写r)  运行程序 输入 where 查看程序出错位置 输入 pirnt(简写p) 后面跟变量名   查看变量的值 输入 quit 退出GDB调试器

【Linux】gdb调试core文件

编写服务器端程序,很容易遇到Crash问题,比较幸运的是Linux提供了core file,保留了Crash的现场.有时候,根据当前的调用栈,并且打印出当前栈的变量就可以分析出crash的原因,但是,有时候看到调用栈却束手无策.下面就介绍自己通过GDB的几个命令的结合,发现一个crash的原因的过程. 下面让我们一起进入现场,来逐步发现其中的原因. 首先,还是运行gdb 命令,gdb wbxgs core.5797,来看看现场. [[email protected] bin]# gdb wbxg

Linux下GDB调试与对拍(先挖个坑)

应为NOIP要复赛在NOI-Linux下编写程序,所以被迫选择Vim+Gdb(主要是Guide太丑了). 虽然GUIDE的调试功能已经对付大多数的调试,反正学一学GDB的使用也没什么坏处. 1 生成调试信息 要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行文件中.使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点.如: gcc -g hello.c -o hello g++ -g hello.cpp -o hello 如果没有-g,你将看不见程序的函数名.变量名,

Hi35xx NVR GDB调试

Hi35xx NVR GDB调试   1. 下载gdb源码 嵌入式Linux 的GDB 调试环境由Host 和Target 两部分组成,Host 端使用arm-linuxgdb,Target Board 端使用gdbserver.这样,应用程序在嵌入式目标系统上运行,而gdb 调试在Host 端,所以要采用远程调试(remote)的方法.进行GDB 调试,目标系统必须包括gdbserver 程序(在主机上正对硬件平台编译成功后下载到目标机上),宿主机也必须安装GDB 程序.一般Linux 发行版