GDB调试手册

Linux 包含了一个叫gdb 的GNU 调试程序。gdb 是一个用来调试C和C++程序的强力调试器。它使你能在程序运行时观察程序的内部结构和内存的使用情况。以下是 gdb 所提供的一些功能:它使你能监视你程序中变量的值、它使你能设置断点以使程序在指定的代码行上停止执行、它使你能一行行的执行你的代码。在命令行上键入gdb并按回车键就可以运行gdb 了。(Windows需要安装MinGW或者CygWin并且需要配置环境变量才可以使用)

 

GDB 命令行参数

启动 GDB

l  gdb executable

l  gdb -e executable -c core-file

l  gdb executable -pid process-id

(使用命令 'ps -auxw' 可以查看进程的 pid

选项

含义

–help
-h

列出命令行参数。

–exec=file
-e file

指定可执行文件。

–core=core-file
-c core-file

指明 core 文件。

–command=file
-x file

从指定文件中读取 gdb 命令。

–directory=directory
-d directory

把指定目录加入到源文件搜索路径中。

–cd=directory

以指定目录作为当前路径来运行 gdb 

–nx
-n

不要执行 .gdbinit 文件中的命令。默认情况下,这个文件中的命令会在所有命令行参数处理完后被执行。

–batch

在非交互模式下运行 gdb 。从文件中读取命令,所以需要 -x 选项。

–symbols=file
-s file

从指定文件中读取符号表。

-write

允许对可执行文件和 core 文件进行写操作。

–quiet
-q

不要打印介绍和版权信息。

–tty=device

指定 device 为运行程序的标准输入输出。

–pid=process-id
-p process-id

指定要附属的进程 ID 

 

GDB命令

GDB 中使用的命令:

命令

描述

help

列出 gdb 帮助信息。

help topic

列出相关话题中的 gdb 命令。

help command

列出命令描述信息。

apropos search-word

搜索相关的话题。

info args
i args

列出运行程序的命令行参数。

info breakpoints

列出断点。

info break

列出断点号。

info break breakpoint-number

列出指定断点的信息。

info watchpoints

列出观察点。

info registers

列出使用的寄存器。

info threads

列出当前的线程。

info set

列出可以设置的选项。

Break and Watch

 

break funtion
break line-number

在指定的函数,或者行号处设置断点。

break +offset
break -offset

在当前停留的地方前面或后面的几行处设置断点。

break file:func

在指定的file文件中的func处设置断点。

break file:nth

在指定的file文件中的第nth行设置断点。

break *address

在指定的地址处设置断点。一般在没有源代码时使用。

break line-number ifcondition

如果条件满足,在指定位置设置断点。

break line threadthread-number

在指定的线程中中断。使用info threads可以显示线程号。

tbreak

设置临时的断点。中断一次后断点会被删除。

watch condition

当条件满足时设置观察点。

clear
clear func
clear nth

清除函数func处的断点。
清除第nth行处的断点。

delete
d

删除所有的断点或观察点。

delete breakpoint-number
delete range

删除指定的断点,观察点。

disable breakpoint-number-or-range
enable breakpoint-number-or-range

不删除断点,仅仅把它设置为无效,或有效。
例子:
显示断点: info break
设置无效: disable 2-9

enable oncebreakpoint-number

设置指定断点有效,当到达断点时置为无效。

enable del breakpoint-number

设置指定断点有效,当到达断点时删除它。

finish

继续执行到函数结束。

Line Execution

 

step
s
step number-of-steps-to-perform

进入下一行代码的执行,会进入函数内部。

next
n
next number

执行下一行代码。但不会进入函数内部。

until
until line-number

until line-number ifcondition

继续运行直到到达指定行号,或者函数,地址等。

return
return expression

弹出选中的栈帧(stack frame)。如果后面指定参数,则返回表达式的值。

stepi
si
nexti
ni

执行下一条汇编/CPU指令。

info signals
info handle
handle SIGNAL-NAMEoption

当收到信号时执行下列动作:nostop(不要停止程序),stop(停止程序执行),print(显示信号),noprint(不显示),pass/noignore(允许程序处理信号),nopass/ignore(不让程序接受信号)

where

显示当前的行号和所处的函数。

Program Stack

 

backtrace
bt
bt inner-function-nesting-depth
bt -outer-function-nesting-depth

显示当前堆栈的追踪,当前所在的函数。

backtrace full

打印所有局部变量的值。

frame number
number

选择指定的栈帧。

up number
down number

向上或向下移动指定个数的栈帧。

info frame addr

描述选中的栈帧。

info args
info all-reg
info locals
info catch

显示选中栈帧的参数,局部变量,异常处理函数。all-reg也会列出浮点寄存器。

Source Code

 

list
l
list line-number
list function
list -
list start#,end#
list filename:function

列出相应的源代码。

set listsize count
show listsize

设置list命令打印源代码时的行数。

directory directory-name
dir directory-name
show directories

在源代码路径前添加指定的目录。

directory

当后面没有参数时,清除源代码目录。

Examine Variables

 

print variable
variable
file::variable
p 'file'::variable

打印指定变量的值。

p *array-var@length

打印arrary-var中的前length项。

p/x var

以十六进制打印整数变量var

p/d var

把变量var当作有符号整数打印。

p/u var

把变量var作为无符号整数打印。

p/o var

把变量var作为八进制数打印。

p/t var
x/b address
x/b &variable

以整数二进制的形式打印var变量的值。

p/c variable

当字符打印。

p/f variable

以浮点数格式打印变量var

p/a variable

打印十六进制形式的地址。

x/w address
x/4b &variable

打印指定的地址,以四字节一组的方式。

call expression

类似于print,但不打印 void 

disassem addr

对指定地址中的指令进行反汇编。

Controlling GDB

 

set gdb-option value

设置 GDB 的选项。

set print array on
set print array off
show print array

以可读形式打印数组。默认是 off 

set print array-indexes on
set print array-indexes off
show print array-indexes

打印数组元素的下标。默认是 off 

set print pretty on
set print pretty off
show print pretty

格式化打印 C 结构体的输出。

set print union on
set print union off
show print union

打印 C 中的联合体。默认是 on 

set print demangle on
set print demangle off
show print demangle

控制 C++ 中名字的打印。默认是 on 

Working Files

 

info files
info share

列出当前的文件,共享库。

file file

file当作调试的程序。如果没指定参数,丢弃。

core file

file当作 core 文件。如果没指定参数,则丢弃。

exec file

file当作执行程序。如果没指定参数,则丢弃。

symbol file

file中读取符号表。如果没指定参数,则丢弃。

load file

动态链入file文件,并读取它的符号表。

path directory

把目录directory加入到搜索可执行文件和符号文件的路径中。

Start and Stop

 

run
r
run command-line-arguments
run < infile > outfile

从头开始执行程序,也允许进行重定向。

continue
c

继续执行直到下一个断点或观察点。

continue number

继续执行,但会忽略当前的断点number次。当断点在循环中时非常有用。

kill

停止程序执行。

quit
q

退出 GDB 调试器。

GDB 操作提示

l   在编译可执行文件时需要给 gcc 加上 "-g" 选项,这样它才会为生成的可执行文件加入额外的调试信息。

l  不要使用编译器的优化选项,比如: "-O""-O2"。因为编译器会为了优化而改变程序流程,那样不利于调试。

l   GDB 中执行 shell 命令可以使用:shell command

l  GDB 命令可以使用 TAB 键来补全。按两次 TAB 键可以看到所有可能的匹配。

l  GDB 命令缩写:例如 info bre 中的 bre 相当于 breakpoints


gdb -tui 代码窗口相关命令(CTRL + X + a):

info win 显示窗口的大小

layout next 切换到下一个布局模式

layout prev 切换到上一个布局模式

layout src 只显示源代码

layout asm 只显示汇编代码

layout split 显示源代码和汇编代码

layout regs 增加寄存器内容显示

focus cmd/src/asm/regs/next/prev 切换当前窗口

refresh 刷新所有窗口

tui reg next 显示下一组寄存器

tui reg system 显示系统寄存器

update 更新源代码窗口和当前执行点

winheight name +/- line 调整name窗口的高度

tabset nchar 设置tab为nchar个字符

gdb在执行中,会自动跟踪代码


GDB  Emacs 中的操作:

emacs 按键

动作

M-x gdb

切换到 gdb 模式。

C-h m

显示 gdb 模式介绍信息。

M-s

等同于gdb 中的 step 命令。

M-n

等同于gdb 中的 next 命令。

M-i

等同于gdb 中的 stepi 命令。

C-c C-f

等同于gdb 中的 finish 命令。

M-c

等同于gdb 中的 continue 命令。

M-u

等同于gdb 中的 up 命令。

M-d

等同于gdb 中的 down 命令。


DB调试实践二(gdb找不到动态库,对运行中的进程生成core文件)

最近使用GDB调试程序的一点经验之谈:

1、程序运行中生成一个Core文件便于保护现场,调试程序,gcore可以满足这种需求:

gcore:对正在运行的进程生成一个内存转储文件,方便保护现场。例如:

–     gcore -s -c test.core pid

–     用-s选项使进程在转储过程中处于停止状态,可以保证转储文件的一致性。若不用-c选项指定转储文件名,则会使用默认的core.pid形式的文件名。

 

2、我的linux虚拟机中调试程序时,发现直接run程序没问题,但gdb调试的时候就提示找不到某个动态库

原因如下:

1)我的虚拟机里同一个用户下由于要编译测试多个不同版本的代码,而每个版本都有不同的运行环境(如:PATH、LD_LIBRARY_PATH等环境变量设置)

2)我目前使用csh,为了快速切换不同的编译环境,我把运行环境所需的环境变量写到不同的.cshrc脚本中,需要切换时运行source .cshrc_XXX

3) GDB调试程序时会启一个新的shell,而且新shell启动时使用默认的.cshrc脚本,从而导致上述的问题,从本质上来说GDB使用的shell的环境非我们要调试程序所需的shell环境设置

 

解决方法:

1)最简单:将所有动态库的查找位置都设置到默认.cshrc中的LD_LIBRARY_PATH的环境变量中

2)其他方法有待探索

 

下面转载一篇不错的gdb总结

gdb高级用法

•         fin(ish):持续运行至当前堆栈帧结束,并显示返回值。

•         adv(ance) [LOC]:持续运行至指定的位置。例如:

–     adv func

–     adv *0x40107b

•         att(ach) pid:将gdb附加到指定的进程上并中断在该进程当前执行位置处。

•         det(ach):使gdb不再附加在当前进程上并恢复被调试进程的运行。

•         info addr <symbol>:查找指定符号对应的地址。

•         info sym <addr>:查找指定地址对应的符号。

•         当符号自动补全的范围太大时可以用单引号开头强制前缀匹配,这样来补全C++类成员很方便。

•         bt [full]:查看所有堆栈帧,若加上full选项则还会显示每个堆栈帧内的局部变量值。

•         f(rame) [FRAMENO]:选择或显示当前堆栈帧。

•         up/down:将向上/向下一层的堆栈帧作为当前选择的帧。

 

常用辅助调试工具

•         gcore:对正在运行的进程生成一个内存转储文件,方便保护现场。例如:

–     gcore -s -c test.core pid

–     用-s选项使进程在转储过程中处于停止状态,可以保证转储文件的一致性。若不用-c选项指定转储文件名,则会使用默认的core.pid形式的文件名。

•         pstack:查看转储文件/正在运行的进程中的完整堆栈帧。例如:

–     pstack -t -O pid/corefile

–     用-t选项可以显示提取堆栈帧时进程被pstack暂停的时间;用-O选项可以显示堆栈帧中每个函数所处目标文件的完整路径。

–     默认情况下,为了保证结果的一致性,pstack在提取堆栈帧时会暂停对应进程的活动,但在进程逻辑对时间很敏感时这样可能导致逻辑混乱引起进程崩溃;此时可以使用-n选项强制pstack不暂停要查看的进程,不过相应地取得的堆栈帧数据就有可能出现问题。

•         truss:仅用于FreeBSD,跟踪命令行或已运行进程的系统调用序列和信号。例如:

–     跟踪命令行:truss /bin/echo hello

–     跟踪已运行的进程:truss -p 1377

•         strace:可用于FreeBSD/Linux,功能同truss相近,输出结果详细一些,包含了系统调用的具体参数。一般用法同truss。

•         ltrace:可用于FreeBSD/Linux,跟踪命令行或已运行进程的运行库调用序列。一般用法同truss。

•         ktrace/kdump:它们是FreeBSD提供的内核级进程跟踪工具,会监控进程的系统调用、文件系统节点转换、信号处理等各种内核级操作。用法:

–     跟踪命令行并记录在ktrace.out中:ktrace command

–     跟踪活动进程并记录在ktrace.out中:ktrace -p pid

–     关闭所有跟踪活动:ktrace -C

–     显示ktrace.out中的跟踪结果:kdump

•         valgrind:x86硬件虚拟机,其中的memcheck模块可用来检测程序是否存在内存泄漏:

–     valgrind -v --num-callers=20 --leak-check=yes --leak-resolution=high--show-reachable=yes command

–     结果中的LEAK SUMMARY总结了内存泄漏情况,其中需要注意的是definitely lost和possibly lost两部分。

 

调试建议

•         产品程序在编译时留下尽可能多的调试符号信息(用-g3选项编译),这些信息不会减慢运行速度,但在出现问题时对调试工作很有帮助。

•         调试用程序不使用优化,并关闭STL的存储池分配方式,这样可以避免valgrind错误地报告内存泄漏,选项为-O0 -g3 –DGLIBCXX_FORCE_NEW


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值