gdb

来源:互联网 发布:阿里云域名价格 编辑:程序博客网 时间:2024/05/21 14:41

1、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调试


二、分析例子

代码如下:

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2.   
  3.   
  4. int add_range(int low, int high);  
  5.   
  6. int add (int a, int b);  
  7.   
  8. int add (int a, int b) {  
  9.     int result = a + b;  
  10.     return result;  
  11. }  
  12.   
  13. int add_range(int low, int high)  
  14. {  
  15.     int i = 0sum = 0;  
  16.     for (i = low; i <= high; i++)  
  17.         sum = sum + i;  
  18.     return sum;  
  19. }  
  20.   
  21. int main(void)  
  22. {  
  23.     int result[100];  
  24.     result[0] = add_range(1, 10);  
  25.     result[1] = add_range(1, 100);  
  26.     printf("result[0]=%d\nresult[1]=%d\n", result[0], result[1]);  
  27.     int a = 9b = 10;  
  28.         int result1 = a + b;  
  29.         int result2 = a * b;  
  30.         printf("result1 = %d, result2 = %d", result1, result2);  
  31.         int result3 = add(result1, result2) ;  
  32.         printf("result3=%d", result3);  
  33.         if (result3 == 10) {  
  34.            printf("result3 = %d", result3);  
  35.         } else {  
  36.            printf("result != 10");   
  37.     }  
  38.         return 0;  
  39. }  


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

 命令如下:

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. gcc -g main.c -o hello1  
  2. gdb hello1  

如下图


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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. list 1  



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

我们退出gdb命令如下

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. quit  

我们这里先不退出

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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. start  
如下图

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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. n  

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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. s  

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

可见当前的add_range函数是被main函数调用的,main传进来的参数是low=1, high=100main函数的栈帧编号为1,add_range的栈帧编号为0。现在可以用info命令(简写为i)查看add_range函数局部变量的值:

i locals

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

(gdb) f 1

输入下面命令

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. i locals  

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

我们也可以修改sum的值

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. set var sum = 0  

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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. finish   

quit     退出命令

3、总结

      我们熟悉了gdb基本的调试命令,然后下篇博客来讲gdb怎么打断点,怎么调试,怎么watch变量。


=========================     断点    ===========================

1 、安装GDB

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. sudo apt-get install gdb  

2 、怎么打断点

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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. break 行号  

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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. break 函数名  

3、设置条件断点

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. break 行号 if 条件  

3、举例分析

hello2.c源文件如下

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. #include<stdio.h>  
  2.   
  3. int main() {   
  4.    int a = 1b = 2c = 3;  
  5.    int i;  
  6.    printf("hello chenyu");    
  7.    for (i = 0 ; i < 100; i++) {  
  8.         ++a;  
  9.         if (i > 90) {  
  10.             ++b;  
  11.         } else {  
  12.             ++c;  
  13.         }  
  14.    }   
  15.    printf("a = %d, b = %d, c = %d", a, b, c);  
  16.    int cc = 0;  
  17.    for (cc; cc < 9; cc++) {  
  18.         printf("c %d", i);  
  19.    }  
  20.    return 0;  
  21. }  

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

1、编译

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. gcc -g hello2.c  

2、gdb调试

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. gdb hello2  

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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. list  
3次回车

4 、然后输入下面打断点命令

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. break 10  
  2.   
  3. break 18  

图片如下:


5 、 运行并且跳转到断点

1、运行

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. start  

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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. c  

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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. r  

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

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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. watch b  

我们看变量的值或则单个变量的值可以用下面命令

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. i locals  
  2.   
  3. p c  

进入函数内部用下面命令

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. s  

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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. n  

删除断点

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. delete 行号  

退出gdb命令

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. quit  

4、如何保存断点

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

1、查看断点信息并保存

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. info b  

2 、保存断点

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. save breakpoint fig.dp  

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

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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. gdb hello2 -x fig.dp  

要记住加上参数 -x 

然后再去查看是否有断点

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. info b  

可以看到是有2个断点的

5、总结

       学会了gdb打断点的基本命令,还有一些调试手段,以及断点的保存。


0 0