【申明:本文仅限于自我归纳总结和相互交流,有纰漏还望各位指出。 联系邮箱:[email protected]】
谈到GDB,不能不对他的强大功能所折服,在我所用过的所有调试器中,这实在是一个强大的调试工具,今天就说说GDB的简单用法。GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在 UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。
GDB常用命令:
awatch |
指定一个变量,如果这个变量被读或者被写,则暂停程序运行,在调试器中显示信息,并等待下一个调试命令。参考rwatch和watch命令。 |
backtrace |
显示函数调用得所有栈框架(stack frames)的 踪迹和当前函数的参数的值,bt是这个命令的简写。 |
break |
设置一个断点,这个命令需要指定代码行或者函数名作为参数 |
clear |
删除一个断点,这个命令需要制定代码行或者函数名作为参数 |
continue |
调试器停止的地方继续执行 |
Ctrl-C |
在当前位置停止执行正在执行的程序,断点在当前行 |
disable |
禁止断点功能,这个命令需要禁止的断点在断点列表索引值作为参数 |
display |
在断点的停止的地方,显示指定的表达式的值。(显示变量) |
enable |
允许断点功能,这个命令需要允许的断点在断点列表索引值作为参数 |
finish |
继续执行,知道当前函数返回 |
ignore |
忽略某个断点制定的次数。例:ignore 4 23忽略断点4的23次运行,在第24次的时候中断 |
info breakpoints |
查看断点信息 |
info display |
查看设置的需要显示的表达式的信息 |
kill |
终止当前debug的进程 |
list |
显示10行代码。如果没有提供参数给这个命令,则从当前行开始显示10行代码。如果提供了函数名作为参数,则从函数开头显示。如果提供代码行的编号作为参数,这一行作为开头显示。 |
load |
动态载入一个可执行文件到调试器。 |
next |
执行下一行的源代码的所有指令。如果是函数调用,则也当作一行源代码,执行到此函数返回 |
nexti |
执行下一行的源代码中的一条汇编指令 |
|
显示变量的值 |
ptype |
显示变量的类型 |
return |
强制从当前函数返回 |
run |
从程序开始的地方执行 |
rwatch |
指定一个变量,如果这个变量被读,则暂停程序运行,在调试器中显示信息,并等待下一个调试命令。参考rwatch和watch命令。 |
set |
设置变量的值。例如:set nval=54将把54保存到nval变量中 |
step |
继续执行程序下一行源代码的所有指令。如果是调用函数,这个命令将进入函数的内部,单步执行函数中代码。 |
stepi |
继续执行程序下一行源代码中的汇编指令。如果是函数调用,这个命令将进入函数的内部,单步执行函数中的汇编代码。 |
txbreak |
在当前函数的退出的点上设置一个临时的断点(只可使用一次)。 |
undisplay |
删除一个display设置的变量显示。这个命令需要将display list中的索引做参数。 |
watch |
指定一个变量,如果这个变量被写,则暂停程序运行,在调试器中显示信息,并等待下一个调试命令。参考rwatch和watch命令。 |
whatis |
显示变量的值和类型。 |
xbreak |
在当前函数的退出的点上设置一个断点。 |
还有其他的一些命令可以用“info gdb”和“gdb -help”查看
调试方式:
参考IBM的一段异常代码进行了测试,具体如下
#include <stdio.h> int wib(int no1, int no2) { int result, diff; diff = no1-no2; result = no1/diff; return result; } int main(int argc, char *argv[]) { int value, div, result, i, total; value = 10; div = 6; total = 0; for(i=0; i<10; i++) { result = wib(value, div); total += result; div++; value--; } printf("%d wibed by %d equals %d\n", value, div, total); return 0; }
第一步:编译
编译的时候注意加-g选项,指定编译器有调试信息
执行命令:gcc gdb_test.c -o gdb_test -g -Wall
第二部:载入
用GDB把可执行文件载入
执行命令:gdb gdb_test
第三步:设置断点
查看源码编号,猜测出错位置或者全速运行报错位置设置断点
执行命令:break
第四步:运行
执行命令:run
第五步:单步调试
单步运行step/next进行调试并打印print
执行命令:run/print
下面是调试过程:
[root@localhost gdb]# gdb gdb_test2 //加载 GNU gdb Fedora (6.8-27.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) (gdb) list 5 //查看 1 #include <stdio.h> 2 3 int wib(int no1, int no2) 4 { 5 int result, diff; 6 diff = no1-no2; 7 result = no1/diff; 8 return result; 9 } 10 int main(int argc, char *argv[]) (gdb) (gdb) (gdb) list 11 { 12 int value, div, result, i, total; 13 value = 10; 14 div = 6; 15 total = 0; 16 17 for(i=0; i<10; i++) 18 { 19 result = wib(value, div); 20 total += result; (gdb) 21 div++; 22 value--; 23 } 24 printf("%d wibed by %d equals %d\n", value, div, total); 25 return 0; 26 } (gdb) (gdb) break 19 //设置断点 Breakpoint 1 at 0x80483d7: file gdb_test2.c, line 19. (gdb) run //运行 Starting program: /mnt/hgfs/E/Work_Code/Interview/gdb/gdb_test2 Breakpoint 1, main () at gdb_test2.c:19 19 result = wib(value, div); (gdb) (gdb) print div //打印值 $5 = 6 (gdb) print value $6 = 10 (gdb) print value $15 = 9 (gdb) print div $16 = 7 (gdb) next //单步调试 20 total += result; (gdb) next 21 div++; (gdb) next 22 value--; (gdb) next 17 for(i=0; i<10; i++) (gdb) print div $17 = 8 (gdb) print value $18 = 8