呓语 | 杨英明的个人博客

专注于c++、Python,欢迎交流

By

GDB调试笔记

参考资料:GDB调试精粹及使用实例

# 调试实例

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 int f[100][100];
 5 int ax,ay;
 6 int bx,by;
 7 int dx[4]={1,0,-1,0};
 8 int dy[4]={0,1,0,-1};
 9 int _count=0;
10 int _min=9999999;
11 int n,m,k;
12 
13 void dfs(int d,int t,int curx,int cury)
14 {
15     if(t>_min)
16         return ;
17     if(curx<0 || cury<0 || cury>n-1 || curx>m-1)
18         return ;
19     if(f[cury][curx])
20         return ;
21     if(curx==by && cury==bx){
22         if(t<_min){
23             _count=0;
24             _min=t;
25         }
26         else{
27             _count++;
28         }
29         return ;
30     }
31     f[cury][curx]=true;
32     if(d==-1){
33         for(int i=0;i<4;i++){
34             bool bt = f[cury+dy[i]][curx+dx[i]];
35             if(!bt){
36                 dfs(i,t+1,curx+dx[i],cury+dy[i]);
37                 if( !(bx==cury+dy[i] && by==curx+dx[i] ))
38                     f[cury+dy[i]][curx+dx[i]]=false;
39             }
40         }
41     }
42     else{
43         for(int i=0;i<4;i++){
44             bool bt = f[cury+dy[i]][curx+dx[i]];
45             int tt=d^2;
46             if(tt==i) continue;
47             if(!bt){
48                 dfs(i,t+1,curx+dx[i],cury+dy[i]);
49                 if( !(bx==cury+dy[i] && by==curx+dx[i] ))
50                     f[cury+dy[i]][curx+dx[i]]=false;
51             }
52         }
53     }
54     return ;
55 }
56 
57 int main()
58 {
59     while(cin>>n>>m>>k){
60         _count=0;
61         _min=99999999;
62         memset(f,0,sizeof(f));
63         for(int i=1;i<=k;i++){
64             int a,b;
65             cin>>a>>b;
66             f[a][b]=true;
67         }
68         cin>>ax>>ay;
69         cin>>bx>>by;
70         dfs(-1,0,ay,ax);
71         cout<<_min<<endl;
72         cout<<_count<<endl;
73     }
74     return 0;
75 }

  这是一道“小鼠迷宫问题”的代码,是道搜索题,要求输出矩阵内a到b的最短路的长度以及最短路的条数。这道题的第一遍代码写完之后,运行后发现堆栈溢出了程序没有输出直接结束。用codeblocks自带的调试debug了一会,发现不是很好用,遂转入cygwin下编译原程序启动gdb调试。顺便也复习了一下gdb的命令。

  下面是我以此程序为例,学习gdb的笔记:

Administrator@PC-201311180010 /cygdrive/d/bin/小鼠迷宫问题
$ g++ -o xs -ggdb main.cpp
-- 编译原程序,并产生调试信息,便于之后进行gdb调试。
•$ g++ -o ex1 -g  ex1.cpp
利用操作系统的native format生成调试信息。GDB 可以直接利用这个信息,其它调试器也可以使用这个调试信息。
•$ g++ -o ex1 -ggdb  ex1.cpp
为 GDB 生成专用的更为丰富的调试信息,但是,此时就不能用其他的调试器来进行调试了 (如 ddx)
(引自L老师课件)

 

Administrator@PC-201311180010 /cygdrive/d/bin/小鼠迷宫问题
$ gdb xs

-- 启动gdb调试原程序。

-- 启动之后会刷出以下内容:

Administrator@PC-201311180010 /cygdrive/d/bin/小鼠迷宫问题
$ gdb xs
GNU gdb (GDB) 7.6.50.20130728-cvs (cygwin-special)
Copyright (C) 2013 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 "i686-pc-cygwin".
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 /cygdrive/d/bin/小鼠迷宫问题/xs...done.
(gdb) 

-- 最后一行(gdb)后面会有一个光标“_”在闪,表示可以输入命令。

 

(gdb) l
46                      f[cury+dy[i]][curx+dx[i]]=false;
47                  }
48              }
49          }
50          return ;
51      }
52
53      int main()
54      {
55          while(cin>>n>>m>>k){

-- list(可简写为 l):显示代码

 

(gdb) l 1
1       #include <iostream>
2       #include <cstring>
3       using namespace std;
4       int f[100][100];
5       int ax,ay;
6       int bx,by;
7       int dx[4]={1,0,-1,0};
8       int dy[4]={0,1,0,-1};
9       int _count=0;
10      int _min=9999999;

-- list 1:从第一行显示代码

 

(gdb) l
11      int n,m,k;
12
13      void dfs(int d,int t,int curx,int cury)
14      {
15          if(curx<0 || cury<0 || cury>n-1 || curx>m-1)
16              return ;
17          if(f[cury][curx])
18              return ;
19          if(curx==by && cury==bx){
20              if(t<_min){

-- 继续显示代码

 

=============== 插入一下 ================

这个时候我看命令行里代码有堆起来了,想清理一下,结果尝试性的输入命令“cls”和“clear”,发现这两个命令是行不通的。

(gdb) cls
Undefined command: "cls".  Try "help".
(gdb) clear
No source file specified.

好吧,既然不行,我们继续。

======================================

 

(gdb) b dfs
Breakpoint 1 at 0x401186: file main.cpp, line 15.

-- breakpoint dfs:在函数dfs入口处设置断点

-- breakpoint 1 表示这是第一个断点

 

(gdb) r
Starting program: /cygdrive/d/bin/小鼠迷宫问题/xs
[New Thread 2144.0xdc0]
[New Thread 2144.0x155c]
4 4 1 1 1 0 0 2 2

Breakpoint 1, dfs (d=-1, t=0, curx=0, cury=0) at main.cpp:15
15          if(curx<0 || cury<0 || cury>n-1 || curx>m-1)

-- run:运行程序。

-- run 命令运行之后,光标会停下来闪烁,表示在等待输入数据。输入数据之后会直接运行到第一个断点处停止,并显示相关信息。

 

(gdb) c
Continuing.

Breakpoint 1, dfs (d=0, t=1, curx=1, cury=0) at main.cpp:15
15          if(curx<0 || cury<0 || cury>n-1 || curx>m-1)

-- continue:继续运行。

 

========== 小问题 ============

(gdb) b dfs if curx==3 && cury==3
Note: breakpoint 1 also set at pc 0x401186.
Breakpoint 2 at 0x401186: file main.cpp, line 15.
(gdb) c
Continuing.

Breakpoint 1, dfs (d=0, t=1, curx=1, cury=0) at main.cpp:15
15          if(curx<0 || cury<0 || cury>n-1 || curx>m-1)

第一条gdb命令设置一个条件断点为第二个断点,第二条gdb命令为继续运行,为何继续运行后不是跳到刚设置的第二个断点处呢?

===========================

 

(gdb) p curx
$1 = 1

-- print:显示一个变量的值

 

========== 小例子 ==========

(gdb) p curx
$1 = 1
(gdb) p
$2 = 1
(gdb) p
$3 = 1
(gdb) p cury
$4 = 0
(gdb) p
$5 = 0

连续输入p会持续显示上一次观察的变量的值。

==========================

 

====== 小问题:这时候连续输入“continue”会发生什么呢? =======

(gdb) c
Continuing.

Breakpoint 1, dfs (d=0, t=2, curx=2, cury=0) at main.cpp:15
15          if(curx<0 || cury<0 || cury>n-1 || curx>m-1)
(gdb) c
Continuing.

Breakpoint 1, dfs (d=0, t=3, curx=3, cury=0) at main.cpp:15
15          if(curx<0 || cury<0 || cury>n-1 || curx>m-1)
(gdb) c
Continuing.

Breakpoint 1, dfs (d=0, t=4, curx=4, cury=0) at main.cpp:15
15          if(curx<0 || cury<0 || cury>n-1 || curx>m-1)
(gdb) c
Continuing.

Breakpoint 1, dfs (d=1, t=4, curx=3, cury=1) at main.cpp:15
15          if(curx<0 || cury<0 || cury>n-1 || curx>m-1)

会连续显示第一个断点处的变化。

===========================================

 

还有其它常用命令:

(gdb) s
17          if(f[cury][curx])
(gdb) s
19          if(curx==by && cury==bx){
(gdb) s
s20             if(t<_min){
(gdb) s
21                  _count=0;
(gdb) s
22                  _min=t;
(gdb) s
27              return ;

-- step:单步执行,等效于step into(可进入函数)。

与之相对的

-- next(n):单步执行,等效于step over(只在当前函数中执行)。

-- finish(f):跳出当前函数,等效于step out。

 

(gdb) b dfs if curx==2 && cury==2
Breakpoint 1 at 0x401186: file main.cpp, line 15.

-- b dfs if curx==2 && cury==2:设置条件断点,程序执行到符合条件处停止。

 

(gdb) watch i
Hardware watchpoint 2: i
(gdb) s
45                  if(!bt){
(gdb) s
41              for(int i=0;i<4;i++){
(gdb) s
Hardware watchpoint 2: i

Old value = 1
New value = 2
0x00401443 in dfs (d=0, t=11, curx=1, cury=2) at main.cpp:41

-- watch:设置一个监测点(数据断点),被检测变量在程序中出现时,显示其变化。

 

(gdb) i b
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x00401186 in dfs(int, int, int, int)
                                           at main.cpp:15
        stop only if curx==2 && cury==2
        breakpoint already hit 1 time
5       breakpoint     keep y   0x00401186 in dfs(int, int, int, int)
                                           at main.cpp:14
6       breakpoint     keep y   0x004011bc in dfs(int, int, int, int)
                                           at main.cpp:17

-- info breakpoint:显示当前所有断点信息。

 

(gdb) d b 1
Ambiguous delete command "b 1": bookmark, breakpoints.
(gdb) d breakpoint 1
(gdb) i b
Num     Type           Disp Enb Address    What
5       breakpoint     keep y   0x00401186 in dfs(int, int, int, int)
                                           at main.cpp:14
6       breakpoint     keep y   0x004011bc in dfs(int, int, int, int)
                                           at main.cpp:17

-- delete breakpoint 断点号:删除指定断点

 

(gdb) d
Delete all breakpoints? (y or n) y
(gdb) i b
No breakpoints or watchpoints.

-- delete:删除当前所有断点

 

 

Freecode : www.cnblogs.com/yym2013

##原创声明 **转载请注明:[呓语](http://www.yangyingming.com) » [GDB调试笔记](http://www.yangyingming.com/article/284)**