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 \n", result );
24 printf("result[1-250] = %d \n", func(250) );
25 }
编译生成执行文件:
gcc –g test.c –o test
使用 GDB 调试:
gdb test ——————启动 GDB
GNU gdb 5.1.1
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-suse-linux"...
(gdb) list ——————从第一行列出源码
1 #include
2
3 int func(int n)
4 {
5 int sum=0,i;
6 for(i=0; i19 {
20 result += i;
(gdb) break 16 ——————设置断点,在源程序第 16 行处。
Breakpoint 1 at 0x8048496: file tst.c, line 16.
(gdb) break func ——————设置断点,在函数 func()入口处。
Breakpoint 2 at 0x8048456: file tst.c, line 5.
(gdb) info break ——————查看断点信息。
Num Type Disp Enb Address What
1 breakpoint keep y 0x08048496 in main at tst.c:16
2 breakpoint keep y 0x08048456 in func at tst.c:5
(gdb) run ——————运行程序
Starting program: /home/hchen/test/tst
Breakpoint 1, main () at tst.c:17 ——————在断点处停住。
17 long result = 0;
(gdb) 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) 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) print i ——————打印变量 i 的值。
$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 ——————p 是 print 的缩写
$4 = 3
(gdb) bt ——————查看函数堆栈
#0 func (n=250) at tst.c:5
#1 0x080484e4 in main () 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
24 printf("result[1-250] = %d \n", func(250) );
Value returned is $6 = 31375
(gdb) continue
Continuing.
result[1-250] = 31375 ——————程序输出。
Program exited with code 027.——————程序退出,调试结束。
(gdb) quit ——————退出 gdb
好了,有了以上的感性认识,还是让我们来系统的认识一下 gdb 吧。
使用 GDB
一般来说 GDB 主要调试的是 C/C++程序。要调试 C/C++程序,首先在编译时,我们必须
要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的-g 参数可以做到这一点,如:
$ cc –g hello.c –o hello
$ g++ -g hello.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 命令来查看,如下所示:
(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" followed by command name for full documentation.
Command name abbreviations 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 at 0x8048458: file hello.c, line 10.
示例二:敲入 b 按两次 TAB 键,你会看到所有 b 开头的命令:
(gdb) b
backtrace break bt
示例三:只记得函数的前缀,可以这样:
(gdb) b make_<按 TAB 键>
make_a_section_from_file make_environ
make_abs_section make_function_type
make_blockvector make_pointer_type
make_cleanup make_reference_type
make_command make_symbol_completion_list
(gdb) b make_
GDB 把所有 make 开头的函数全部列出来给你查看。
示例四:调试 C++程序,可以函数名一样。如:
(gdb) b ‘bubble(<按两次 TAB 键>
bubble(double,double) bubble(int,int)
(gdb) b ‘bubble
你可以查看到 C++中所有的重载函数以及参数
要退出 GDB,只要 quit 或命令简称 q 就行了。
GDB 中运行 UNIX 的 Shell 程序
在 gdb 环境中,你可以执行 UNIX 的 shell 命令,使用 gdb 的 shell 命令来完成:
shell
调用 UNIX 的 shell 来执行,环境变量 SHELL 中定义的 UNIX 的 shell
将会被用来执行,如果 SHELL 没有定义,那就使用 UNIX 的标准 shell:
/bin/sh
还有一个 gdb 命令是 make:
make
可以在 gdb 中执行 make 命令来重新 build 自己的程序。这个命令等价于“make make ”
在 GDB 中运行程序
1、 当以`
set args 可指定运行时参数。(如:set args 10 20 30 40 50)
show args 命令可以查看设置好的运行参数。
2、 运行环境
path可设定程序的运行路径。
show paths 查看程序的运行路径。
set environment varname[=value]设置环境变量。如:set env USER=hchen
show environment[varname]查看环境变量
3、 工作目录
cd 相当于 shell 的 cd 命令。
pwd 显示当前的工作目录。
4、 程序的输入输出
info terminal 显示程序用到的终端的模式
使用重定向空值程序输出。如 run>outfile
tty 命令可以指定写输入输出的终端设备。如 tty /dev/ttyb
调试已运行的程序
两种方法:
1、 在 UNIX 下用 ps 查看正在运行的程序的 PID(进程 ID),然后用 gdb
PID
格式挂接正在运行的程序。
2、 先用 gdb关联上源代码,并进行 gdb,在 gdb 中用 attach 命令来挂接进程的
PID,并用 detach 来取消挂接的程序。
暂停/恢复程序运行
调试程序中,暂停进程运行时必须的,GDB 可以方便的暂停程序的运行。你可以设置程
序在哪停住,在什么条件下停住,在收到什么信号时停住等等。你便于你查看运行的变量,
以及运行时的流程。
当进程被 gdb 停住时,你可以使用 info program 来查看程序是否在运行、进程号、被暂停
的原因。
在 gdb 中,我们可以有以下几种暂停方式:断点(breakpoint)、观察点(watchpoint)、捕
捉点(catchpoint)、信号(signals)、线程停止(thread stops)。如果要恢复程序运行,可以
使用 c 或者 continue 命令。
一、设置断点(breakpoint)
我们用 break 命令设置断点。下面有几点设置断点的方法:
break
在进入指定函数时停住。C++中可以使用 class::function 或 function(type,type)格式来指
定函数名。
break
在指定行号停住。
break +offset
break –offset
在当前行号的前面或者后面的 offset 行停住。Offset 为自然数。
break filename:linenum
在源文件 filename 的 linenum 行处停住。
break filename:function
在源文件 filename 的 function 函数的入口处停住。
break *address
在程序运行的内存地址处停住。
break
break 命令没有参数时,表示在下一条指令处停住。
break…if
…可以是上述的参数,condition 表示条件,在条件成立时停住。比如在循环体
中,可以设置 break if i=100,表示当 i 为 100 时停住程序。
查看断点时,可使用命令 info 命令,如下所示:(注:n 表示断点号)
info breakpoints[n]
info break[n]
二、 设置捕捉点(catchpoint)
我们可以设置捕捉点来捕捉程序运行时的一些事件。如:载入共享库(动态链接库)或
是 C++的异常,设置捕捉点的格式为:
catch
当 event 发生时,停住程序。Event 可以是下面的内容:
1、throw 一个 C++抛出的异常(throw 为关键字),
2、catch 一个 C++捕捉到的异常(catch 为关键字),
3、exec 调用系统调用 exec 时(exec 为关键字,目前此功能只在 HP-UX 下有用)
4、fork 调用系统调用 fork 时。(fork 为关键字,目前此功能只在 HP-UX 下有用)
5、vfork 调用系统调用 vfork 时。(vfork 为关键字,目前此功能只在 HP-UX 下
有用)
6、load 或 load 载入共享库(动态链接库)时。(load 为关键字,
目前此功能只在 HP-UX 下有用)
7、 unload 或 unload 卸载共享库(动态链接库)时。(unload 为关
键字,目前此功能只在 HP-UX 下有用)
tcatch
只设置一次捕捉,当程序停住后,断点被自动删除。
三、 维护停止点
上面说了如何设置程序的停止点,GDB 中的停止点也就是上述的三类。在 GDB 中,如
果你觉得已定义好的停止点没有用了,你可以使用 delete、clear、disable、enable 这几个
命令来进程维护。
clear
清楚所有已定义的停止点。
clear
clear
清楚所有设置在函数上的停止点。
clear
clear
清楚所有设定在指定行上的停止。
delete [breakpoints][range…]
删除指定的断点,breakpoints 为断点号。如果不指定断点号,则表示删除所有的