一个调试示例
源程序:tst.c
代码:
1 #include
2
3 int func(intn)
4 {
5 int sum=0,i;
6 for(i=0; i
7 {
8 sum+=i;
9 }
10 return sum;
11 }
13
14 main()
15 {
16 int i;
17 long result = 0;
18 for(i=1; i <=100; i++)
19 {
20 result += i;
21 }
22
23 printf("result[1-100] = %d ",result );
24 printf("result[1-250] = %d ",func(250) );
25 }
编译生成执行文件:(Linux下)
hchen/test> cc -g tst.c -o tst
使用GDB调试:
代码:
hchen/test> gdb tst <----------启动GDB
GNU gdb 5.1.1
Copyright 2002 FreeSoftware Foundation, Inc.
GDB is freesoftware, covered by the GNU General Public License, and you are
welcome to changeit and/or distribute copies of it under certain conditions.
Type "showcopying" to see the conditions.
There is absolutelyno warranty for GDB. Type "show warranty" for details.
This GDB wasconfigured as "i386-suse-linux"...
(gdb) l <-------------------- l命令相当于list,从第一行开始例出原码。
1 #include
2
3 int func(intn)
4 {
5 int sum=0,i;
6 for(i=0; i
7 {
8 sum+=i;
9 }
10 return sum;
(gdb) <-------------------- 直接回车表示,重复上一次命令
11 }
12
14 main()
15 {
16 int i;
17 long result = 0;
18 for(i=1; i<=100; i++)
19 {
20 result += i;
(gdb) break 16 <-------------------- 设置断点,在源程序第16行处。
Breakpoint 1 at0x8048496: file tst.c, line 16.
(gdb) break func <-------------------- 设置断点,在函数func()入口处。
Breakpoint 2 at0x8048456: file tst.c, line 5.
(gdb) info break <-------------------- 查看断点信息。
Num Type Disp EnbAddress What
1 breakpoint keep y0x08048496 in main at tst.c:16
2 breakpoint keep y0x08048456 in func at tst.c:5
(gdb) r <--------------------- 运行程序,run命令简写
Starting program:/home/hchen/test/tst
Breakpoint 1, main() at tst.c:17 <---------- 在断点处停住。
17 long result = 0;
(gdb) n <--------------------- 单条语句执行,next命令简写。
18 for(i=1; i<=100; i++)
(gdb) n
20 result += i;
(gdb) n
18 for(i=1; i<=100; i++)
(gdb) n
20 result += i;
(gdb) c <--------------------- 继续运行程序,continue命令简写。
Continuing.
result[1-100] =5050 <----------程序输出。
Breakpoint 2, func(n=250) at tst.c:5
5 int sum=0,i;
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p i <--------------------- 打印变量i的值,print命令简写。
$1 = 134513808
(gdb) n
8 sum+=i;
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p sum
$2 = 1
(gdb) n
8 sum+=i;
(gdb) p i
$3 = 2
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p sum
$4 = 3
(gdb) bt <--------------------- 查看函数堆栈。
#0 func (n=250) attst.c:5
#1 0x080484e4 inmain () at tst.c:24
#2 0x400409ed in__libc_start_main () from /lib/libc.so.6
(gdb) finish <--------------------- 退出函数。
Run till exit from#0 func (n=250) at tst.c:5
0x080484e4 in main() at tst.c:24
24printf("result[1-250] = %d
", func(250));
Value returned is$6 = 31375
(gdb) c <--------------------- 继续运行。
Continuing.
result[1-250] =31375 <----------程序输出。
Program exited withco
(gdb) q <--------------------- 退出gdb。
hchen/test>
好了,有了以上的感性认识,还是让我们来系统地认识一下gdb吧。
使用GDB
一般来说GDB主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点。如:
> cc -g hello.c-o hello
> g++ -ghello.cpp -o hello
如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。当你用-g把调试信息加入之后,并成功编译目标代码以后,让我们来看看如何用gdb来调试他。
启动GDB的方法有以下几种:
1、gdb
program也就是你的执行文件,一般在当然目录下。
2、gdb core
用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件。
3、gdb
如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试他。program应该在PATH环境变量中搜索得到。
GDB启动时,可以加上一些GDB的启动开关,详细的开关可以用gdb -help查看。我在下面只例举一些比较常用的参数:
-symbols
-s
从指定文件中读取符号表。
-se file
从指定文件中读取符号表信息,并把他用在可执行文件中。
-core
-c
调试时core dump的core文件。
-directory
-d
加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径。
GDB的命令概貌
启动gdb后,就你被带入gdb的调试环境中,就可以使用gdb的命令开始调试程序了,gdb的命令可以使用help命令来查看,如下所示:
/home/hchen> gdb
GNU gdb 5.1.1
Copyright 2002 FreeSoftware Foundation, Inc.
GDB is freesoftware, covered by the GNU General Public License, and you are
welcome to changeit and/or distribute copies of it under certain conditions.
Type "showcopying" to see the conditions.
There is absolutelyno warranty for GDB. Type "show warranty" for details.
This GDB wasconfigured as "i386-suse-linux".
(gdb) help
List of classes ofcommands:
aliases -- Aliasesof other commands
breakpoints --Making program stop at certain points
da
files -- Specifyingand examining files
internals --Maintenance commands
obscure -- Obscurefeatures
running -- Runningthe program
stack -- Examiningthe stack
status -- Statusinquiries
support -- Supportfacilities
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" followed by command name for full documentation.
Command nameabbreviations are allowed if unambiguous.
(gdb)
gdb的命令很多,gdb把之分成许多个种类。help命令只是例出gdb的命令种类,如果要看种类中的命令,可以使用help 命令,如:help breakpoints,查看设置断点的所有命令。也可以直接help 来查看命令的帮助。
gdb中,输入命令时,可以不用打全命令,只用打命令的前几个字符就可以了,当然,命令的前几个字符应该要标志着一个唯一的命令,在Linux下,你可以敲击两次TAB键来补齐命令的全称,如果有重复的,那么gdb会把其例出来。
示例一:在进入函数func时,设置一个断点。可以敲入break func,或是直接就是b func
(gdb) b func
Breakpoint 1 at0x8048458: file hello.c, line 10.
示例二:敲入b按两次TAB键,你会看到所有b打头的命令:
(gdb) b
backtrace break bt
(gdb)
示例三:只记得函数的前缀,可以这样:
(gdb) b make_ <按TAB键>
(再按下一次TAB键,你会看到:)
make_a_section_from_filemake_environ
make_abs_sectionmake_function_type
make_blockvectormake_pointer_type
make_cleanupmake_reference_type
make_commandmake_symbol_completion_list
(gdb) b make_
GDB把所有make开头的函数全部例出来给你查看。
示例四:调试C++的程序时,有可以函数名一样。如:
(gdb) b 'bubble(M-?
bubble(double,double)bubble(int,int)
(gdb) b 'bubble(
你可以查看到C++中的所有的重载函数及参数。(注:M-?和“按两次TAB键”是一个意思)
要退出gdb时,只用发quit或命令简称q就行了。