使用GDB调试程序

97 篇文章 7 订阅

使用GDB调试程序


在Linux下常常需要调试自己的程序,通常使用GDB这个工具来帮助。

[test1280@localhost gdbtest]$ uname -a
Linux localhost.localdomain 2.6.32-431.el6.i686 #1 SMP Fri Nov 22 00:26:36 UTC 2013 i686 i686 i386 GNU/Linux
[test1280@localhost gdbtest]$ which gdb
/usr/bin/gdb
[test1280@localhost gdbtest]$ 

先看下一个简单的C程序:

#include <stdio.h>
#include <stdlib.h>

void print_array(int *parr, int n)
{
	int i;
	for (i=0; i<n; i++)
	{
		printf("%d ", parr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[5] = {9, 1, 5, 3, 7};
	int val = 11;
	arr[4] = val;
	print_array(arr, 5);
	return 0;
}

GDB调试命令:

file   加载被调试的可执行程序文件。
r (run)运行被调试的程序。如果有断点,则将停止在第一个断点处;如果没有断点,则将整个程序运行完。
c (continue)继续执行被调试的程序,直到下一个断点或者程序结束。
b (break)设置断点,后面可以加函数名称或者是行号。
d (delete)删除断点。
s (step)执行下一行源代码,如果有函数调用则进入被调用函数内部。
n (next)执行下一行源代码,即使此行中包含了一个函数调用,也一并执行,并不会进入被调用函数内部。
p (print)打印指定变量的值。
i (info)用于显示各类信息。
q (quit)退出GDB调试交互环境。
help   帮助信息。

[test1280@localhost gdbtest]$ gcc -o main main.c
[test1280@localhost gdbtest]$ gdb
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...(no debugging symbols found)...done.
(gdb) 

再进行编译链接时没有指定-g参数,那么使用gdb调试会产生:no debugging symbols found的提示;

在编译时指定-g选项:

[test1280@localhost gdbtest]$ gcc -o main main.c -g
[test1280@localhost gdbtest]$ gdb
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) 

现在开始调试:

上面已经使用了第一个命令file,用来加载对应的可执行程序文件。

file  file_name;

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) run
Starting program: /home/test1280/gdbtest/main 
9 1 5 3 11 

Program exited normally.

由于我们没有设置断点,那么执行run时,将把整个程序都执行。

注:所有的命令简写与完全的都是等价的,即:r等价于run,i等价于info……

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) break main
Breakpoint 1 at 0x8048442: file main.c, line 16.
(gdb) b 4
Breakpoint 2 at 0x80483fa: file main.c, line 4.
(gdb) r
Starting program: /home/test1280/gdbtest/main 

Breakpoint 1, main () at main.c:16
16		int arr[5] = {9, 1, 5, 3, 7};
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
(gdb) c
Continuing.

Breakpoint 2, print_array (parr=0xbffff708, n=5) at main.c:7
7		for (i=0; i<n; i++)
(gdb) c
Continuing.
9 1 5 3 11 

Program exited normally.
(gdb) 

break main指明在main函数处设置断点;
b 4指明在源文件第4行设置断点;

设置完断点后,使用r开始执行,可以看到在main处停止,

16 int arr[5] = {9, 1, 5, 3, 7};

代表的是下一行是这行源代码。

然后使用c(continue命令),继续执行程序,直到下一个断点,也就是第四行。

在第四行使用c,继续执行程序,由于没有断点,则直接将整个程序都执行完了。

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) b 19
Breakpoint 1 at 0x804847a: file main.c, line 19.
(gdb) i b
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x0804847a in main at main.c:19
(gdb) info b
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x0804847a in main at main.c:19
(gdb) i break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x0804847a in main at main.c:19
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x0804847a in main at main.c:19
(gdb) r
Starting program: /home/test1280/gdbtest/main 

Breakpoint 1, main () at main.c:19
19		print_array(arr, 5);
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
(gdb) s
print_array (parr=0xbffff708, n=5) at main.c:7
7		for (i=0; i<n; i++)
(gdb) s
9			printf("%d ", parr[i]);
(gdb) 

使用s可以看到进入了被调用函数内部。

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) b 19
Breakpoint 1 at 0x804847a: file main.c, line 19.
(gdb) i b
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x0804847a in main at main.c:19
(gdb) r
Starting program: /home/test1280/gdbtest/main 

Breakpoint 1, main () at main.c:19
19		print_array(arr, 5);
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
(gdb) n
9 1 5 3 11 
20		return 0;
(gdb) n
21	}
(gdb) n
0x00aa2d26 in __libc_start_main () from /lib/libc.so.6
(gdb) n
Single stepping until exit from function __libc_start_main,
which has no line number information.

Program exited normally.
(gdb) 

使用n可以看到,即使在断点处存在函数调用,也会一并执行,区别于s(step)命令。

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) b 19
Breakpoint 1 at 0x804847a: file main.c, line 19.
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x0804847a in main at main.c:19
(gdb) b print_array
Breakpoint 2 at 0x80483fa: file main.c, line 7.
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x0804847a in main at main.c:19
2       breakpoint     keep y   0x080483fa in print_array at main.c:7
(gdb) delete 1
(gdb) i b
Num     Type           Disp Enb Address    What
2       breakpoint     keep y   0x080483fa in print_array at main.c:7
(gdb) 

使用info break(i b)可以显示断点信息,使用delete 编号可以删除对应的断点。

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) b print_array
Breakpoint 1 at 0x80483fa: file main.c, line 7.
(gdb) r
Starting program: /home/test1280/gdbtest/main 

Breakpoint 1, print_array (parr=0xbffff708, n=5) at main.c:7
7		for (i=0; i<n; i++)
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
(gdb) n
9			printf("%d ", parr[i]);
(gdb) n
7		for (i=0; i<n; i++)
(gdb) n
9			printf("%d ", parr[i]);
(gdb) print i
$1 = 1
(gdb) print parr[i]
$2 = 1
(gdb) n
7		for (i=0; i<n; i++)
(gdb) n
9			printf("%d ", parr[i]);
(gdb) n
7		for (i=0; i<n; i++)
(gdb) n
9			printf("%d ", parr[i]);
(gdb) n
7		for (i=0; i<n; i++)
(gdb) n
9			printf("%d ", parr[i]);
(gdb) n
7		for (i=0; i<n; i++)
(gdb) n
11		printf("\n");
(gdb) n
9 1 5 3 11 
12	}
(gdb) 

上面的执行过程可以看到执行了printf但是并没有输出,这是为什么呢?

我个人认为这个是由于“行缓冲”的关系,直到遇到换行符才ffluash下。

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) b print_array
Breakpoint 1 at 0x80483fa: file main.c, line 7.
(gdb) r
Starting program: /home/test1280/gdbtest/main 

Breakpoint 1, print_array (parr=0xbffff708, n=5) at main.c:7
7		for (i=0; i<n; i++)
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
(gdb) n
9			printf("%d ", parr[i]);
(gdb) n
7		for (i=0; i<n; i++)
(gdb) b 11
Breakpoint 2 at 0x804842b: file main.c, line 11.
(gdb) info b
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x080483fa in print_array at main.c:7
	breakpoint already hit 1 time
2       breakpoint     keep y   0x0804842b in print_array at main.c:11
(gdb) c
Continuing.

Breakpoint 2, print_array (parr=0xbffff708, n=5) at main.c:11
11		printf("\n");
(gdb) n
9 1 5 3 11 
12	}
(gdb) q
A debugging session is active.

	Inferior 1 [process 2901] will be killed.

Quit anyway? (y or n) y
[test1280@localhost gdbtest]$ 

当在一个循环中时,可以设置一个在外部的断点,然后使用c执行,可以跳出这个循环。

(gdb) file main
Reading symbols from /home/test1280/gdbtest/main...done.
(gdb) help
List of classes of commands:

aliases -- Aliases of other commands
breakpoints -- Making program stop at certain points
data -- Examining data
files -- Specifying and examining files
internals -- Maintenance commands
obscure -- Obscure features
running -- Running the program
stack -- Examining the stack
status -- Status inquiries
support -- Support facilities
tracepoints -- Tracing of program execution without stopping the program
user-defined -- User-defined commands

Type "help" followed by a class name for a list of commands in that class.
Type "help all" for the list of all commands.
Type "help" followed by command name for full documentation.
Type "apropos word" to search for commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb) help info
Generic command for showing things about the program being debugged.

List of info subcommands:

info address -- Describe where symbol SYM is stored
info all-registers -- List of all registers and their contents
info args -- Argument variables of current stack frame
info auto-load -- Print current status of auto-loaded files
info auto-load-scripts -- Print the list of automatically loaded Python scripts
info auxv -- Display the inferior's auxiliary vector
info bookmarks -- Status of user-settable bookmarks
info breakpoints -- Status of user-settable breakpoints
info catch -- Exceptions that can be caught in the current stack frame
info checkpoints -- IDs of currently known checkpoints
info classes -- All Objective-C classes
info common -- Print out the values contained in a Fortran COMMON block
info copying -- Conditions for redistributing copies of GDB
info dcache -- Print information on the dcache performance
info display -- Expressions to display when program stops
info extensions -- All filename extensions associated with a source language
info files -- Names of targets and files being debugged
info float -- Print the status of the floating point unit
info frame -- All about selected stack frame
info functions -- All function names
info handle -- What debugger does when program gets various signals
info inferiors -- IDs of currently known inferiors
---Type <return> to continue, or q <return> to quit---q
Quit
(gdb) q
[test1280@localhost gdbtest]$

可以单独使用help命令,也可以使用help来具体显示某一个命令。

以上仅仅是GDB的最简单的功能,后续会继续介绍GDB更加强大的功能。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值