linux下gdb调试基本命令学习

   我们知道软件开发,调试技能是一个必备技能,学会调试就能快速高效地抓到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

linux下gdb调试基本命令学习_第1张图片

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

[zoulei@CentOS test]$ gdb

linux下gdb调试基本命令学习_第2张图片

2.查看源码

#(gdb)list

(gdb) help l
List 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) l
21           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 20
Breakpoint 1 at 0x80486cd: file sqlite.c, line 20.
(gdb) run
Starting program: /home/zoulei/test/a.out
[Thread debugging using libthread_db enabled]

Breakpoint 1, main (argc=1, argv=0xbffff774) at sqlite.c:20
20           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 breakpoints
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x080486cd in main at sqlite.c:20
        breakpoint already hit 1 time
5.取消断点

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

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

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

(gdb) break 60
Breakpoint 1 at 0x804884f: file sqlite.c, line 60.
(gdb) run
Starting program: /home/zoulei/test/a.out
[Thread debugging using libthread_db enabled]
You have opened a sqlite3 database named user successfully!
table SensorData already exists

Breakpoint 1, main (argc=1, argv=0xbffff774) at sqlite.c:61
61            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 breakpoints
No breakpoints or watchpoints.
(gdb) break 70
Breakpoint 2 at 0x80488f7: file sqlite.c, line 70.
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/zoulei/test/a.out
[Thread debugging using libthread_db enabled]
You have opened a sqlite3 database named user successfully!
table SensorData already exists
nrow=33 ncolumn=5
the 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) start
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Temporary 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:20
20           sqlite3 *db=NULL;
(gdb) step
22           int i=0;
(gdb) next
23           int nrow=0;
(gdb) bt
#0  main (argc=1, argv=0xbffff774) at sqlite.c:23
(gdb) next
24           int ncolumn = 0;
(gdb) next
25           char *zErrMsg =NULL;
(gdb) next
26           char **azResult=NULL; //二维数组存放结果
(gdb) next
28           len = sqlite3_open("user",&db);
(gdb) bt
#0  main (argc=1, argv=0xbffff774) at sqlite.c:28
(gdb) step
29           if( len )
(gdb) bt
#0  main (argc=1, argv=0xbffff774) at sqlite.c:29
7.列出调用栈

#(gdb)backtrace

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

(gdb) run
Starting program: /home/zoulei/test/a.out
[Thread debugging using libthread_db enabled]
You have opened a sqlite3 database named user successfully!
table SensorData already exists
nrow=51 ncolumn=5
the result is:

Program received signal SIGSEGV, Segmentation fault.
0x00bc7a4f in __strlen_ia32 () from /lib/libc.so.6
Missing 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还有很多的命令,因为没用到过,就暂时总结到这里了,以后若学到好的调试方法,再来更新!


你可能感兴趣的:(linux基础学习)