调试的例子
[root@localhost 20121130]# gdb mmap
GNU gdb Fedora (6.8-37.el5)
Copyright (C) 2008 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 "i386-redhat-linux-gnu"...
(gdb) break 11
Breakpoint 1 at 0x80484b7: file mmap.c, line 11.
(gdb) run
Starting program: /home/admin/c/20121130/mmap
Breakpoint 1, main () at mmap.c:11
11 int fd=-1;
(gdb) n
12 char *buf="quick brown fox jumps over the lazy dog."
(gdb) n
13 char *ptr=NULL;
(gdb) n
14 char *temp="aaa";
(gdb) n
16 fd=open("test.txt",O_RDWR|O_CREAT|O_TRUNC,S_IRWXU);
(gdb) n
17 if(-1==fd)
(gdb) p fd
$1 = 6
(gdb) pt full
No symbol "full" in current context.
(gdb) pt
type = int
(gdb) n
22 int ls=lseek(fd,LEN-1,SEEK_SET);
(gdb) n
23 int size=write(fd,temp,2);
(gdb) n
25 ptr=(char*)mmap(NULL,LEN,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
(gdb) n
26 if((char*)-1==ptr)
(gdb) n
33 memcpy(ptr+16,buf,strlen(buf));
(gdb) n
34 munmap(ptr,LEN);
(gdb) n
35 close(fd);
(gdb) n
36 return 0;
(gdb) n
37 }
(gdb) n
0x008c4e9c 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
一般来说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>
program也就是你的执行文件,一般在当然目录下。
2、gdb <program> core
用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件。
3、gdb <program> <PID>
如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试他。program应该在PATH环境变量中搜索得到。
GDB启动时,可以加上一些GDB的启动开关,详细的开关可以用gdb -help查看。我在下面只例举一些比较常用的参数:
-symbols <file>
-s <file>
从指定文件中读取符号表。
-se file
从指定文件中读取符号表信息,并把他用在可执行文件中。
-core <file>
-c <file>
调试时core dump的core文件。
-directory <directory>
-d <directory>
加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径。
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) | 执行下一行语句,如果有函数调用则进入到函数中 |
break(或b) 行号 | 在某一行设置断点 |
break 函数名 | 在某个函数开头设置断点 |
break ... if ... | 设置条件断点 |
continue(或c) | 从当前位置开始连续运行程序 |
delete breakpoints | 删除断点 |
display 变量名 | 跟踪查看某个变量,每次停下来都显示它的值 |
disable breakpoints | 禁用断点 |
enable 断点号 | 启用断点 |
info(或i)breakpoints | 查看当前设置了哪些断点 |
run(或r) | 从头开始连续运行程序 |
undisplay 跟踪显示号 | 取消跟踪显示 |
watch | 设置观察点 |
info(或i) watchpoints | 查看当前设置了哪些观察点 |
x | 从某个位置开始打印存储单元的内容,全部当成字节来看, 而不区分哪个字节属于哪个变量 |