您的位置:首页 > 运维架构 > Linux

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

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

一、gdb简介

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

1.启动被调试的程序。

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

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

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

二、gdb使用流程

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

<span style="font-size:24px;">#include <stdio.h>
 
void myprint(int res)
{
    printf("result= %d \n", res);
}
 
void main(void)
{
    inti;
    longresult = 0;
       for(i=1;i<=100; i++)
       {
       result+= i;
       }
    myprint(result);
}</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的内容如下:

<span style="font-size:18px;">#include <stdio.h> 
 
int EnterScore ( int P_array[] ) ;
void find ( int P_array[] , int count ) ;
 
int main ( void )
{
    intarray[5] , count ;
    EnterScore( array ) ;  
    find( array , count ) ;
    return0 ;
}
 
int EnterScore ( int P_array[] )
{
    intcount = 0 ;
    do
    { 
       printf( "Enter students' score : \n" ) ; 
       scanf( "%d" , &(P_array[count]) ) ;  
       count++;
    }while ( P_array[ count - 1 ] != -1 ) ;
    returncount ;
}
 
 
void find ( int P_array[] , int count )
{
    intx , y , i ;
    printf( "Enter the students' score's scope : \n" ) ;
    scanf( "%d,%d" , &x , &y ) ;
    for( i = 0 ; i < count ; i++ )
    { 
       if( P_array[i] >= x && P_array[i] <= y ) 
       {  
           printf( "The score is %d.\n" , P_array[i] ) ; 
       }
    }
} </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,就可以了,下面

其他的错误我没有发现,就总结到这里吧,如有不正确的地方,还请指出,大家共同进步。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: