linux应用编程笔记(1)gdb调试方法及如何找出dbg.c程序中的错误

原文链接:http://blog.csdn.net/deep_l_zh/article/details/48656079


摘要: 介绍了gdb调试器以及其使用流程,总结了常用的几个gdb调试命令,最后使用这些方法找出dgb.c文件中的错误。


一、gdb简介

    gdb是gnu发布的一款功能强大的程序调试工具,其主要功能有如下三个:

    1.启动被调试的程序。

   2.让被调试的程序在指定的位置停住。

   3.当程序停住时,可以检查程序状态,例如变量的值。

    我们在gcc编译成功以后,运行程序还会出现逻辑错误,这样的错误需要调试,那么使用gdb就可以。


二、gdb使用流程

    这里编写一个测试函数gdb-test.c来延时gdb的使用流程,函数如下:

[cpp]  view plain  copy
  1. <span style="font-size:24px;">#include <stdio.h>  
  2.    
  3. void myprint(int res)  
  4. {  
  5.     printf("result= %d \n", res);  
  6. }  
  7.    
  8. void main(void)  
  9. {  
  10.     inti;  
  11.     longresult = 0;  
  12.        for(i=1;i<=100; i++)  
  13.        {  
  14.        result+= i;  
  15.        }  
  16.     myprint(result);  
  17. }</span>  

    这个函数就是在for循环里实现result的自加,然后打印出来这个值。

    在编写好函数之后,可以按照下面的流程使用gdb:

    1.编译时加上-g选项

    # gcc –g gdb-test.c –o gdb-test

    2.启动gdb

    # gdb gdb-test

    这时候gdb就会启动,启动后的信息如下:

   3.在main函数时设置端点

    第一个休息点,一般设置为main函数:

    #break main

   4.运行程序

    #run

   5.利用更多的命令对程序进行调试。

    下面对gdb的更多命令总结。


三、gdb命令

    list(l)查看程序

    可以使用list查看程序。
    break(b) 函数名 在某函数入口处添加断点

    设置端点之后,程序运行到这里就会停住,这里可以指定函数名。
    break(b) 行号 在指定行添加断点

    指定到哪一行停住
    break(b) 文件名:行号 在指定文件的指定行添加断点

    用于多文件编译,可以设置在哪个文件中的哪一行设置断点。
    info break 查看所有设置的断点

    查看我们已经设置了哪些端点,按照次序会从1开始排序,哪些不需要的可以使用delete删除。
    delete 断点编号 删除断点

    next(n)单步运行程序(不进入子函数)
    step(s) 
单步运行程序(进入子函数)
    continue(c) 
继续运行程序

    从当前位置急需运行,知道下一个断点停住。
    print(p) 变量名 查看指定变量值
    set var=value 设置变量的值
    quit(q) 退出gdb

    以上命令都可以在上面编写的测试函数里进行测试,这里就不粘贴出来了。


四、调试dgb.c并找出其中的错误

    dgb.c的内容如下:

[cpp]  view plain  copy
  1. <span style="font-size:18px;">#include <stdio.h>   
  2.    
  3. int EnterScore ( int P_array[] ) ;  
  4. void find ( int P_array[] , int count ) ;  
  5.    
  6. int main ( void )  
  7. {  
  8.     intarray[5] , count ;  
  9.     EnterScore( array ) ;    
  10.     find( array , count ) ;  
  11.     return0 ;  
  12. }  
  13.    
  14. int EnterScore ( int P_array[] )  
  15. {  
  16.     intcount = 0 ;  
  17.     do  
  18.     {   
  19.        printf( "Enter students' score : \n" ) ;   
  20.        scanf( "%d" , &(P_array[count]) ) ;    
  21.        count++;  
  22.     }while ( P_array[ count - 1 ] != -1 ) ;  
  23.     returncount ;  
  24. }  
  25.    
  26.    
  27. void find ( int P_array[] , int count )  
  28. {  
  29.     intx , y , i ;  
  30.     printf( "Enter the students' score's scope : \n" ) ;  
  31.     scanf( "%d,%d" , &x , &y ) ;  
  32.     for( i = 0 ; i < count ; i++ )  
  33.     {   
  34.        if( P_array[i] >= x && P_array[i] <= y )   
  35.        {    
  36.            printf( "The score is %d.\n" , P_array[i] ) ;   
  37.        }  
  38.     }  
  39. } </span>  

    这个函数的功能,输入五个学生的成绩,直到输入-1的时候,停止输入,接着输入一个分数的范围,然后输出在这个范围内的学生的成绩。

    我们将其编译,加上调试选项:

    #gcc –g dgb.c –o dgb

    编译通过,然后运行:

    #./dgb

    然后出现了Enter students' score :

    我分别输入了五个成绩:11,22,33,44,55,然后输入-1,开始要求Enter the students' score's scope :,然后我输入20,30,没有任何输出信息。

    这就所谓的逻辑错误,程序在编译的时候没有语法错误,但是却得不到我们想要的值,刚才的操作步骤如下图:

    

    那么我们开启gdb调试,来看看问题到底出在哪里:

    #gdb dgb

    #break main

    #run

    然后我们在两个重要的函数之前都加上断点:

    #break EnterScore

    #break find

    在find之前,我们需要准备好两个参数,一个是数组,一个是count,我们的EnterScore做的就是这两个事情,那么我们让程序运行到find之前:

    #continue

    #continue

    这时候程序需要你输入学生的成绩,按照我刚才的输入11,22,33,44,55,然后输入结束输入-1,之后运行到find之前停住了,我们打印一下当前的变量:

    #printcount

    发现这个值是-1!-1的话,肯定就错了,传到下面去的话,就没有办法进行查找了,再打印一下数组里面的值:

    #printP_arry[0]

    #printP_arry[1]

    #printP_arry[2]

    #printP_arry[3]

    #printP_arry[4]

    前面五个分别输出11,22,33,44,55,这里说明get成绩是对了,但是count是错误的。

    看EnterScore,在它里面count=0,然后每次输入一个数,count都会自加1,但是最后return count的值之后,下面没有哪一个语句有比如count= EnterScore,这种右值调用方式,我们可以切进去看看,在EnterScore里面,还未退出函数之前,count的值是多少,这里在return之前设置一个断点:

    #break 23

    然后重新运行程序:

    #run

    #continue

   这时候停在了EnterScore这里我们打印一下count的值:

    #printcount

    输出是0!

    #continue

    这时候我们输入分数11,22,33,44,55然后输入-1,之后就停在了return count这个地方,我们再打印一下:

    #printcount

    输出6!为什么是6呢?在这个函数里显然是对的,因为我们输入了6次,最后一次输入-1,做判断while ( P_array[ count - 1 ] != -1 ) ;也是机会判断P_array[ 5] != -1,不过这时候我有个疑问,因为我们在定义数组的时候int array[5]只分配给了它5个单元,这里已经到了P_array[ 5],也就是第六个单元了,会不会造成数组越界,导致core dump呢?刚才运行的时候还没有,不知道是我判断错了,还是编译器比较“健壮”。

    这里先不管这个,先把count的事儿解决了,这里count还是6怎么到了find就变成了-1呢?我们继续运行:

    #continue

    然后再打印count的值:

    #printcount

    又变成-1了,这个-1是哪里来的呢?我也不知道具体哪里来的,但是我可以肯定的是这个count和我们EnterScore里面的count是不一样的,所以这里我们做出修改,把EnterScore的返回值count赋给find,具体修改如下:

    intmain ( void )

{

    intarray[5] , count_enter ;

    count_enter=EnterScore( array ) ;  

    find( array , count_enter ) ;

    return0 ;

}

    我只把main函数里面原来定义的count改为了count_enter,然后把EnterScore的返回值给他,这样它就拿到了真正的count,然后再传给find,这样我们在进行编译:

    #gcc –g dgb.c –o dgb

    #./dgb

    运行后按照刚才的操作,结果一切正常,输出信息如下:

   

    确实打印出来了我们期望的值。但是刚才那个疑问还在,比如我们运行程序,我要输出的分数从0到100,这时候输出信息如下:

   

    这个第六个成绩是哪里来的呢?我们只有五个成绩,而且也没有给6这个值,这是因为count++之后,变为了6,所以,去掉最后在find函数里面做一个小修改就可以了:

    for( i = 0 ; i < count-1 ; i++ )

    把这里的count改为count-1,就可以了,下面

    其他的错误我没有发现,就总结到这里吧,如有不正确的地方,还请指出,大家共同进步。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值