linux下gdb调试基本命令学习

来源:互联网 发布:修改mysql配置文件 编辑:程序博客网 时间:2024/05/22 06:53

   我们知道软件开发,调试技能是一个必备技能,学会调试就能快速高效地抓到bug,而gdb 是 GNU 调试器,Linux 上的标配调试器。下面我就对我所学到的一些在linux下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)执行下一行语句,如果有函数调用则进入到函数中

  下面以我自己编写的操作数据库的sqlite.c文件进行演示:

1.进入gdb

#(gdb) a.out

[zoulei@CentOS test]$ gdb a.out


也可以直接在命令行输入gdb,进入gdb后在提示符(gdb)后输入要调试的可执行文件a.out,不过还要加入gdb的file命令如图:

[zoulei@CentOS test]$ gdb


2.查看源码

#(gdb)list

(gdb) help lList specified function or line.With no argument, lists ten more lines after or around previous listing."list -" lists the ten lines before a previous ten-line listing.One argument specifies a line, and ten lines are listed around that line.Two arguments with comma between specify starting and ending lines to list.Lines can be specified in these ways:  LINENUM, to list around that line in current file,  FILE:LINENUM, to list around that line in that file,  FUNCTION, to list around beginning of that function,  FILE:FUNCTION, to distinguish among like-named static functions.  *ADDRESS, to list around the line containing that address.With two args if one is empty it stands for ten lines away from the other arg.(gdb) l21           int len;22           int i=0;23           int nrow=0;24           int ncolumn = 0;25           char *zErrMsg =NULL;26           char **azResult=NULL; //二维数组存放结果27           /* 打开数据库 */28           len = sqlite3_open("user",&db);29           if( len )30           {
     如果想了解gdb下的调试命令是怎么用的,可以通过在该命令前面加入help,内核就会打印该命令的使用方法,比如上面我输入(gdb)help l 命令后,从英文注释  可以知道list命令可以后跟参数,后跟一个参数可以查看具体某一行的代码,后跟两个参数查看源码中某一行到另一行的具体代码,不跟参数就直接列出当前的10行代码。上面我只演示了不跟参数的情况。

3.设置断点

#(gdb)break n

(gdb) b 20Breakpoint 1 at 0x80486cd: file sqlite.c, line 20.(gdb) runStarting program: /home/zoulei/test/a.out[Thread debugging using libthread_db enabled]Breakpoint 1, main (argc=1, argv=0xbffff774) at sqlite.c:2020           sqlite3 *db=NULL;Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.166.el6_7.3.i686 sqlite-3.6.20-1.el6.i686

 n表示在哪一行设置断点,上面会在运行到源码第20行时停止,可以查看变量的值、堆栈情况等;这个行号是gdb的行号。

4.查看断点处情况

#(gdb)info breakpoints

(gdb) info breakpointsNum     Type           Disp Enb Address    What1       breakpoint     keep y   0x080486cd in main at sqlite.c:20        breakpoint already hit 1 time
5.取消断点

#(gdb)delete +要取消的断点

(gdb) delete 1(gdb) info breakpointsNo breakpoints or watchpoints.(gdb)

下面我就4.5.6三个步骤进行演示:

(gdb) break 60Breakpoint 1 at 0x804884f: file sqlite.c, line 60.(gdb) runStarting program: /home/zoulei/test/a.out[Thread debugging using libthread_db enabled]You have opened a sqlite3 database named user successfully!table SensorData already existsBreakpoint 1, main (argc=1, argv=0xbffff774) at sqlite.c:6161            sql="select *from SensorData";Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.166.el6_7.3.i686 sqlite-3.6.20-1.el6.i686(gdb) delete 1(gdb) info breakpointsNo breakpoints or watchpoints.(gdb) break 70Breakpoint 2 at 0x80488f7: file sqlite.c, line 70.(gdb) runThe program being debugged has been started already.Start it from the beginning? (y or n) yStarting program: /home/zoulei/test/a.out[Thread debugging using libthread_db enabled]You have opened a sqlite3 database named user successfully!table SensorData already existsnrow=33 ncolumn=5the result is:Program received signal SIGSEGV, Segmentation fault.0x00bc7a4f in __strlen_ia32 () from /lib/libc.so.6(gdb)
可以发现通过设置断点,知道在源码的60行到70行之间发生了 Segmentation fault.错误,于是我们就缩小了发生错误的代码的范围。
6.单步调试

#(gdb) step

#  (gdb)   next

(gdb) startThe program being debugged has been started already.Start it from the beginning? (y or n) yTemporary breakpoint 3 at 0x80486cd: file sqlite.c, line 20.Starting program: /home/zoulei/test/a.out[Thread debugging using libthread_db enabled]Temporary breakpoint 3, main (argc=1, argv=0xbffff774) at sqlite.c:2020           sqlite3 *db=NULL;(gdb) step22           int i=0;(gdb) next23           int nrow=0;(gdb) bt#0  main (argc=1, argv=0xbffff774) at sqlite.c:23(gdb) next24           int ncolumn = 0;(gdb) next25           char *zErrMsg =NULL;(gdb) next26           char **azResult=NULL; //二维数组存放结果(gdb) next28           len = sqlite3_open("user",&db);(gdb) bt#0  main (argc=1, argv=0xbffff774) at sqlite.c:28(gdb) step29           if( len )(gdb) bt#0  main (argc=1, argv=0xbffff774) at sqlite.c:29
7.列出调用栈

#(gdb)backtrace

程序运行如果出错,立即执行bt命令,即可看出出错的堆栈地址及相应的出错代码行。

(gdb) runStarting program: /home/zoulei/test/a.out[Thread debugging using libthread_db enabled]You have opened a sqlite3 database named user successfully!table SensorData already existsnrow=51 ncolumn=5the result is:Program received signal SIGSEGV, Segmentation fault.0x00bc7a4f in __strlen_ia32 () from /lib/libc.so.6Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.166.el6_7.3.i686 sqlite-3.6.20-1.el6.i686(gdb) bt#0  0x00bc7a4f in __strlen_ia32 () from /lib/libc.so.6#1  0x00b9223f in vfprintf () from /lib/libc.so.6#2  0x00b99210 in printf () from /lib/libc.so.6#3  0x080488de in main (argc=1, argv=0xbffff774) at sqlite.c:67
可以看出出错的位置在sqlite.c的67行。

感觉gdb调试还是蛮容易学的!无非就是了解这些命令知道怎么用就行。

目前我只学到了这些基本的gdb调试命令,我知道gdb还有很多的命令,因为没用到过,就暂时总结到这里了,以后若学到好的调试方法,再来更新!


原创粉丝点击