作为程序员,调试程序是不可避免的,在windows下常用的IDE比如 keil 软件会有集成的debug图形化调试工具,使用起来非常简单易懂。在linux下虽然没有图形化调试工具,但是gdb作为文本界面的调试工具其功能也是非常强大的,在这里简单介绍gdb的用法。
一.调试准备
1.首先我们编写一个测试程序:
[lwn@VM_255_164_centos temp2]$vim gdbtest.c
/*********************************************************************************
2 * Copyright: (C) 2017 SCUEC
3 * All rights reserved.
4 *
5 * Filename: gdbtest.c
6 * Description: This file
7 *
8 * Version: 1.0.0(04/01/17)
9 * Author: LI WJNG <liwjng@gmail.com>
10 * ChangeLog: 1, Release initial version on "04/01/17 15:19:12"
11 *
12 ********************************************************************************/
13
14 #include <stdio.h>
15
16 int func(int n)
17 {
18 int sum=0,i;
19 for(i=0;i<n;i++)
20 {
21 sum += i;
22 }
23 return sum;
24 }
25
26
27 /********************************************************************************
28 * Description:
29 * Input Args:
30 * Output Args:
31 * Return Value:
32 ********************************************************************************/
33 int main (int argc, char **argv)
34 {
35 int i;
36 long result = 0;
37 int sum = 0;
38 sum = func(10);
39 for(i=0;i<100;i++)
40 {
41 result += i;
42 }
43
44 printf("the result is add 1 to 100 is %d\n",result);
45 printf("the sum is add 1 to %d is %d\n",10,sum);
46 return 0;
47 } /* ----- End of main() ----- */
48
2.编译程序
要使用gdb调试,编译的时候一定要加上 -g 选项,如:gcc -g test.c,否则在gdb命令中l的时候会出现:No symbol table is loaded. Use the "file" command.错误提示;
[lwn@VM_255_164_centos temp2]$ gcc -g gdbtest.c -o test
[lwn@VM_255_164_centos temp2]$ ls
gdbtest.c test
3.使用gdb命令进入调试界面
[lwn@VM_255_164_centos temp2]$ gdb -q test
Reading symbols from /home/lwn/mysrc/temp2/test...done.
(gdb)
二.gdb调试命令:
1.使用list(简写:l) 命令,将看到部分源程序清单。
(gdb) l main
29 * Input Args:
30 * Output Args:
31 * Return Value:
32 ********************************************************************************/
33 int main (int argc, char **argv)
34 {
35 int i;
36 long result = 0;
37 int sum = 0;
38 sum = func(10);
(gdb) help list //可以看到有关list的命令说明
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.
2.运行程序:run(简写:r),break(简写:b) ,continue(简写:c) ,until(简写:u)
(gdb) l main
29 * Input Args:
30 * Output Args:
31 * Return Value:
32 ********************************************************************************/
33 int main (int argc, char **argv)
34 {
35 int i;
36 long result = 0;
37 int sum = 0;
38 sum = func(10);
(gdb) b main //在main函数开始出设置断点
Breakpoint 1 at 0x40056d: file gdbtest.c, line 36.
(gdb) b 38 //在第38行设置断点
Breakpoint 2 at 0x40057c: file gdbtest.c, line 38.
(gdb) i b //命令info break列出所有的断点
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000040056d in main at gdbtest.c:36
breakpoint already hit 1 time
2 breakpoint keep y 0x000000000040057c in main at gdbtest.c:38
breakpoint already hit 1 time
(gdb) r //r命令让程序全速运行
Starting program: /home/lwn/mysrc/temp2/test
Breakpoint 1, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:36 //遇到刚刚设置的第一个断点36行停了下来
36 long result = 0;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-106.el7_2.8.x86_64
(gdb) c //命令contin让程序继续运行
Continuing.
Breakpoint 2, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38 //运行到设置的第二个断点听了下来
38 sum = func(10);
(gdb) u 38//让程序执行到固定某一行
main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38
38 sum = func(10);
3.单步运行next(简写:n) 和step(简写:s)
l (gdb) l //列出相关行的源程序
31 * Return Value:
32 ********************************************************************************/
33 int main (int argc, char **argv)
34 {
35 int i;
36 long result = 0;
37 int sum = 0;
38 sum = func(10);
39 for(i=0;i<100;i++)
40 {
(gdb) b 38 //在调用函数的行设置断点
Breakpoint 3 at 0x40057c: file gdbtest.c, line 38.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/lwn/mysrc/temp2/test
Breakpoint 3, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38
38 sum = func(10);
(gdb) n //可以看到使用next命令之后程序跳到了39行执行
39 for(i=0;i<100;i++)
————————————————————————————————————————————————————————————————————————————————————————————————————
Breakpoint 3, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38
38 sum = func(10);
(gdb) s //同样使用step命令之后可以看到程序进入到了func函数去执行
func (n=10) at gdbtest.c:18
18 int sum=0,i;
4.打印相关信息info(简写:i),print(简写:p),display(简写:disp)
(gdb) r
Starting program: /home/lwn/mysrc/temp2/test
Breakpoint 1, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:36
36 long result = 0;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-106.el7_2.8.x86_64
(gdb) p result //打印result变量的值
$1 = 140737488348608 //因为第36行语句还没执行,所以现在result还未被初始化,现在是一个垃圾值
(gdb) i lo //打印所有局部变量的值
i = 0
result = 140737488348608
sum = 0
(gdb) disp result //每次遇到程序停下来都将显示变量result的值
1: result = 140737488348608
(gdb) c
Continuing.
Breakpoint 2, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:38
38 sum = func(10);
1: result = 0 //result被初始化为0
(gdb) c
Continuing.
Breakpoint 3, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:44
44 printf("the result is add 1 to 100 is %d\n",result);
1: result = 4950 //result为最终的计算值
5.条件控制断点
39 for(i=0;i<100;i++)
40 {
41 result += i;
42 }
(gdb) b 41 //在41行设置断点
Breakpoint 1 at 0x400592: file gdbtest.c, line 41.
(gdb) cond 1 i==10 //当i等于10的时候程序停下来
(gdb) r
Starting program: /home/lwn/mysrc/temp2/test
Breakpoint 1, main (argc=1, argv=0x7fffffffe5c8) at gdbtest.c:41
41 result += i;
(gdb) p i
$1 = 10
(gdb) p result//可以看到当i=10的时候 result 的值为45
$2 = 45
在大多数情况下,灵活使用这些命令已经能够高效的调试程序了,如果对于这些gdb命令还有疑问的可以使用help命令获得详细的帮助信息。
146



被折叠的 条评论
为什么被折叠?



