0. 前言
gdb是一个在UNIX环境下的命令行调试工具。
如果需要使用gdb调试程序,请在gcc时加上-g
选项.
1. 基本命令
序号 | 操作 | 示例 () 内为缩写 |
说明 |
---|---|---|---|
0 | 加载可执行文件 | file <文件名> | 加载的文件应该为可执行文件; 文件名= 路径名(当前目录可省略)+文件名 |
1 | 进入gdb | gdb test | test是要调试的程序; 由gcc test.c -g -o test生成; 进入后提示符变为(gdb) |
2 | 查看源码 | list (l) + <行号>/<函数>/... | 源码会进行行号提示 如果需要查看在其他文件中定义的函数, 在l后加上函数名即可定位到这个函数的定义 及查看附近的其他源码; 或者,使用断点或单步运行, 到某个函数处使用s进入这个函数 |
3 | 设置断点 | break (b) <行号> delete break <num> disable break <num> enable break <num> |
在<行号>处停止,可同时设置多个断点 可以查看变量值,堆栈值等 |
4 | 查看断点信息 | info(i) break(b) | 断点信息是按创建的次序排列,从1开始 |
5 | 运行代码 | run(r) | 运行整个代码到断点处 无断点,直接运行至代码结束 |
6 | 执行程序 | start | 开始执行程序,停在main()函数第一行语句前面,等待命令 |
7 | 单步运行 | step(s) / next(n) | s为单步,当遇到调用函数时,进入该函数; n与s不同为:遇到函数时不进入 |
8 | 继续运行 | continue(c) | 当断点处暂停后, 'c'继续运行到下一个断点或者程序结尾 |
9 | 连续运行 | finish | 连续运行到本函数结束为止,然后停下来等待命令 |
10 | 设置变量值 | set var xxx=xxx | 调试时设置某个变量的值,后续根据该值运行 |
11 | 显示变量值 | print(p) <变量> | 打印出程序中某个变量的在此时的值 |
12 | 观察变量 | watch <变量> | 在某一循环处,往往希望能够观察一个变量的变化情况, 这时就可以键入命令"watch"来观察变量的变化情况 |
13 | 自动打印变量值 | display undisplay |
每次暂停,都将打印出设定变量的值 |
14 | 退出GDB | quit(q) | 退出 |
15 | 帮助信息 | help(h) <命令> | 显示该命令的用法等信息 |
2. 断点调试
命令格式 | 例子 | 作用 |
---|---|---|
break + 设置断点的行号 | break n | 在n行处设置断点 |
tbreak + 行号/函数名 | tbreak n/func | 设置临时断点,到达后被自动删除 |
break + filename + 行号 | break main.c:10 | 用于在指定文件对应行设置断点 |
break + <0x...> | break 0x3400a | 用于在内存某一位置处暂停 |
break + 行号 + if + 条件 | break 10 if i==3 | 用于设置条件断点, 在循环中使用非常方便 |
info breakpoints/watchpoints [n] | info break | n表示断点号, 查看断点/观察点的情况 |
clear + 要清除的断点行号 | clear 10 | 用于清除对应行的断点, 要给出断点的行号, 清除时GDB会给出提示 |
delete + 要清除的断点编号 | delete 3 | 用于清除断点和自动显示的表达式的命令, 要给出断点的编号, 清除时GDB不会给出任何提示 |
disable/enable + 断点编号 | disable 3 | 让所设断点暂时失效/使能, 如果要让多个编号处的断点失效/使能, 可将编号之间用空格隔开 |
awatch/watch + 变量 | awatch/watch i | 设置一个观察点, 当变量被读出或写入时程序被暂停 |
rwatch + 变量 | rwatch i | 设置一个观察点,当变量被读出时,程序被暂停 |
catch | 设置捕捉点来补捉程序运行时的一些事件 如:载入共享库(动态链接库)或是C++的异常 |
|
tcatch | 只设置一次捕捉点, 当程序停住以后, 应点被自动删除 |
3. 数据命令
命令格式 | 示例 | 作用 |
---|---|---|
display +表达式 | display a | 用于显示表达式的值, 每当程序运行到断点处 都会显示表达式的值 |
info display | &essp; | 用于显示当前所有 要显示值的表达式的情况 |
delete + display 编号 | delete 3 | 用于删除一个要显示值的表达式, 被删除的表达式将不被显示 |
disable/enable + display 编号 | disable/enable 3 | 使一个要显示值的表达式暂时失效/使能 |
undisplay + display 编号 | undisplay 3 | 用于结束某个表达式值的显示 |
whatis + 变量 | &essp; whatis i | 显示某个表达式的数据类型 |
print(p) + 变量/表达式 | p n | 用于打印变量或表达式的值 |
set + 变量 = 变量值 | set i = 3 | 改变程序中某个变量的值 在使用print命令时, 可以对变量按指定格式进行输出, 其命令格式为print /变量名 + 格式 其中常用的变量格式: x:十六进制; d:十进制; u:无符号数; o:八进制; c:字符格式; f:浮点数。 |
4. 调试环境相关命令
命令 | 示例 | 说明 |
---|---|---|
set args | set args arg1 arg2 | 设置运行参数 |
show args | show args | 参看运行参数 |
set width + 数目 | set width 70 | 设置GDB的行宽 |
cd + 工作目录 | cd ../ | 切换工作目录 |
run | r/run | 程序开始执行 |
step(s) | s | 进入式(会进入到所调用的子函数中)单步执行, 进入函数的前提是, 此函数被编译有debug信息 |
next(n) | n | 非进入式(不会进入到所调用的子函数中)单步执行 |
finish | finish | 一直运行到函数返回 并打印函数返回时的堆栈地址 和返回值及参数值等信息 |
until + 行数 | u 3 | 运行到函数某一行 |
continue(c) | c | 执行到下一个断点或程序结束 |
return <返回值> | return 5 | 改变程序流程, 直接结束当前函数, 并将指定值返回 |
call + 函数 | call func | 在当前位置执行所要运行的函数 |
5. 堆栈相关命令
命令 | 示例 | 说明 |
---|---|---|
backtrace/bt | bt | 用来打印栈帧指针, 也可以在该命令后加上要打印的栈帧指针的个数, 查看程序执行到此时,是经过哪些函数呼叫的程序, 程序“调用堆栈”是当前函数之前的所有已调用函数的列表(包括当前函数) 每个函数及其变量都被分配了一个“帧”, 最近调用的函数在 0 号帧中(“底部”帧) |
frame | frame 1 | 用于打印指定栈帧 |
info reg | info reg | 查看寄存器使用情况 |
info stack | info stack | 查看堆栈使用情况 |
up/down | up/down | 跳到上一层/下一层函数 |
6. 跳转命令
jump: 指定下一条语句的运行点。可以是文件的行号,可以是file:line格式,可以是+num这种偏移量格式。表式着下一条运行语句从哪里开始。相当于改变了PC寄存器内容,堆栈内容并没有改变,跨函数跳转容易发生错误。
7. 信号命令
命令 | 示例 | 说明 |
---|---|---|
signal | signal SIGXXX | 产生XXX信号,如SIGINT |
handle | handle SIG_XXX | 定义一个信号处理函数 |
8. 运行shell命令
shell + <命令>
9. 更多选型
程序 | 命令 | 说明 |
---|---|---|
程序运行 | set args | 可指定运行时参数 |
show args | 查看设置好的运行参数 | |
运行环境 | path | 设定程序的运行路径 |
show paths | 查看程序的运行路径 | |
set environment varname | 设置环境变量 如:set env USER=hchen |
|
show environment [varname] | 查看环境变量。 | |
工作目录 | cd | 改变工作目录 |
pwd | 打印当前工作目录 | |
输入/输出 | run > file.txt | 重定向到文件 |
线程 | break | 暂停所有线程 |
break pthread_id | 暂停特定线程 |
10. Core文件
Core Dump: Core的意思是内存,Dump的意思是扔出来,堆出来;
开发和使用Unix程序时,有时程序莫名其妙的down了,却没有任何的提示(有时候会提示core dumped), 这时候可以查看一下有没有形如core.进程号的文件生成,这个文件便是操作系统把程序down掉时的内存内容扔出来生成的, 它可以做为调试程序的参考.
(1). 生成Core文件
一般默认情况下,core file的大小被设置为了0,这样系统就不dump出core file了。修改后才能生成core文件。
[niesh@niesh nie]$ ulimit -c unlimited #设置core大小为无限
[niesh@niesh nie]$ ulimit unlimited #设置文件大小为无限
core文件生成路径:输入可执行文件运行命令的同一路径下;
若系统生成的core文件不带其他任何扩展名称,则全部命名为core;
新的core文件生成将覆盖原来的core文件。
1). /proc/sys/kernel/core_uses_pid:
可以控制core文件的文件名中是否添加pid作为扩展。文件内容为1,表示添加pid作为扩展名,生成的core文件格式为core.xxxx;为0则表示生成的core文件同一命名为core。
可通过以下命令修改此文件:echo "1" > /proc/sys/kernel/core_uses_pid
**2). proc/sys/kernel/core_pattern: **
可以控制core文件保存位置和文件名格式。
可通过以下命令修改此文件:echo "/corefile/core-%e-%p-%t" > core_pattern
3).: 统一目录:
可以将core文件统一生成到/corefile目录下,产生的文件名为core-命令名-pid-时间戳, 以下是参数列表:
参数 描述 %p 添加pid %u 添加当前uid %g 添加当前gid %s 添加导致产生core的信号 %t 添加core文件生成时的unix时间 %h 添加主机名 %e 添加命令名
(2). 用gdb查看core文件
发生core dump之后, 用gdb进行查看core文件的内容, 以定位文件中引发core dump的行:
gdb [exec file] [core file]
如: gdb ./test core
或: gdb ./a.out
core-file core.xxxx
gdb后, 用bt
或where
查看程序运行到哪里, 来定位core dump的文件行.
本文转自https://www.cnblogs.com/wuyuegb2312/archive/2013/03/29/2987025.html, 做了部分修改