Debugging with GDB

 代码编译
# 在调试代码时不要打开编译器优化选项
$ gcc -g3 -Wall -Wextra -o test1 test1.c

 

# 完成调试后才使用优化选项
$ gcc -O9 -g3 -Wall -Wextra -o test1 test1.c


Startup Files
~/.gdbinit
./.gdbinit

 

通过参数指定 startup file

$ gdb -command=z-file x

 

启动GDB
开启TUI (Terminal User Interface)界面
$ gdb -tui HegemonyTextLive

ctrl-p  前一个命令
ctrl-n  后一个命令

 

# 调试正在运行中的程序,指定进程号
$ gdb primepipe 2776

 

设置breakpoint

(gdb) break 30

 

# 显示断点信息
(gdb) info break
(gdb) i b             # 缩写


# 清除在30行的breakpoint
(gdb) clear 30
Deleted breakpoint 1

 

# 删除breakpoint,使用标号
(gdb) delete 1 3 4

 

# 一次性的临时断点 temparory breakpoint
(gdb) tbreak foo.c::10

 

# 开启/关闭断点
(gdb) disable 1 3
(gdb) enable 5
(gdb) disable               # 关闭所有
(gdb) enable                # 开启所有
(gdb) enable once 1     # 临时开启,中断1次后即失效

 

执行语句
# 单步语句执行
(gdb) next 3               # 连续执行next 3次
(gdb) step 3               # 连续执行step 3次

 

# 执行到当前函数返回
(gdb) finish

 

# 执行到比当前行号高的行,实际应该是执行到比当前机器指令的内存地址更高的指令处
# 可以用于执行完成当前循环
(gdb) until
(gdb) u 17                  # 执行到17行
(gdb) u swap               # 执行到swap函数入口
(gdb) u swapflaw.c:17  # 执行到swapflaw.c的第17行代码


条件中断
(gdb) break 30 if num_y == 1

 

# 条件中断中使用的library functions必须是返回值类型为int的;
# 由于library没有符号信息,所以gdb无法正确处理返回值非int型的函数
(gdb) break 44 if strlen(mystring) == 0
(gdb) print cos(0.0)
$1 = 14368

 

# 设置/修改端点的条件,使用端点标号
(gdb) condition 1 num_y == 1
(gdb) cond 3               # 取消断点的条件

 

命令列表

# 为断点设置自动执行命令列表
(gdb) commands 1      # 为1号断点设置命令
> silent
> printf "fibonacci was passed %d.\n", n
> continue                 # 继续执行
> end

 

# 命令列表中可以使用被link进程序中的 library functions 或 user-define functions,
# 但是必须是返回值类型为int的函数
(gdb) command 2
> silent
> printf "string has a length of %d\n", strlen(string)
> end

 

# 取消命令列表,通过设置一个空的命令集
(gdb) commands 1
> end


# 定义命令宏
(gdb) define print_and_go
> printf $arg0, $arg1     # 参数列表
> continue
> end
(gdb) commands 1
> silent
> print_and_go "fibonacci was passed %d.\n" n   # 注意参数之间使用空格分隔,不能使用','
> end


# 设置观察点,当表达式的值发生变化是中断,支持组合表达式
# 要求变量在当前代码堆栈中
(gdb) watch z > 28
(gdb) watch (i | j > 12) && i > 24 && strlen(name) > 6

 

查看和修改变量的值
# 自动显示变量值,当遇到断点或者使用next, step命令时自动显示变量当前值
(gdb) disp *tmp

 

# 自动显示开启、关闭及删除命令
(gdb) info disp              # 查询disp的标号
(gdb) dis disp 1            # 关闭1号disp
(gdb) enable disp 1       # 启用1号disp
(gdb) undisp 1              # 删除1号disp


# 调用程序中的函数
(gdb) commands 2
> printf "*********** current tree ***********"
> call printtree(root)      # 调用自定义的debug函数
> end


# 显示动态数组内容
# 格式为:*pointer@number_of_elements
(gdb) p *x@25             # x = (int *)malloc(25*sizeof(int));
$2 = {0, 0, 0, 12, 0 <repeats 21 times>}


# print高级选项
(gdb) p/x y                  # 以16进制显示变量y的值
(gdb) p/c y                   # 以字符类型显示
(gdb) p/s y                  # 以字符串类型显示
(gdb) p/f y                   # 以浮点数类型显示


# 设置变量的值
(gdb) set x = 12            # 修改变量x的当前值
(gdb) set args 1 52 19 11   # 设置程序运行参数,argv[1]:1 ...
(gdb) info args              # 查询运行参数

 

程序CRASH
abort()系统函数会触发 SIGABRT 信号,将导致程序终止并产生 core 文件。

 

使用 file 命令可以查看 core 文件是哪个程序产生的
$ file core
core: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, SVR4-style, from 'sigsegv'

 

多线程环境调试

# 查看线程列表,'*'表示当前所在的线程
(gdb) info threads
* 4 Thread 32771 (LWP 28678) 0x4005ba35 in __pthread_sigsuspend () from /lib/i686/libpthread.so.0
3 Thread 16386 (LWP 28677) 0x4005ba35 in __pthread_sigsuspend () from /lib/i686/libpthread.so.0
2 Thread 32769 (LWP 28676) 0x420db1a7 in poll () from /lib/i686/libc.so.6
1 Thread 16384 (LWP 28653) 0x4005ba35 in __pthread_sigsuspend () from /lib/i686/libpthread.so.0

 

# 切换线程空间
(gdb) thread 3

 

# 为线程设置断点
(gdb) break 88 thread 3               # 当线程3执行到88行时中断
(gdb) break 88 thread 3 if x == y     # 当线程3执行到88行并且变量x和y值相等时中断

 

 

辅助工具
strace 显示程序执行的系统调用(system calls)
$ strace ./a.out

 

ltrace 显示程序执行的库函数调用(library calls)
$ ltrace ./a.out


追踪动态内存使用问题,GUN C Library 提供了以下的工具:
1. MALLOC_CHECK_
2. mcheck()
3. mtrace() 和 mtrace 脚本

 

命令缩写
b         break
i          info
cond    condition
r         run
n         next
s         step
c         continue
p         print
bt        backtrace

 

参考书:《The Art of Debugging with GDB, DDD, and Eclipse》

 

 

posted @ 2011-07-27 12:07  edwardlost  阅读(1092)  评论(0编辑  收藏  举报