gdb使用

21 阅读4分钟

功能:控制程序执行过程,并且观察程序运行状态。

设置断点

gdb有三种断点:普通断点、观察断点和捕捉断点

普通断点break

程序运行到此处,即停止。

break n (简写b n):在第n行处设置断点
break func:在某个函数入口处设置断点
break filename:linenum  :在某个文件的某行设置断点
break filename:func  :在某个文件的某函数处设置断点

观察断点

当观察的变量或者表达式发生变化时,即停止。

watch 变量、表达式:建立观察断点
info watchpoints:查看watchpoint

注意:如果硬件观察点过多导致无法新建观察点。可以尝试删除(禁用)观察点,或者关闭硬件观察点,强制让观察点为软件观察点。
扩展:软件观察点,类似于一段程序,调试程序每运行一行,观察点表达式会进行计算。
硬件观察点,通过寄存器的方式监控变量变化,优点不影响程序运行效率,缺点是由于寄存器数量限制,硬件观察点个数受限。

注意:watchpoints 仅在变量的作用域范围有效

捕捉断点

 `catch` 命令设置 `catchpoint`。你可以捕获各种事件,例如异常、信号、系统调用等。以下是一些示例:

   - 捕获异常抛出事件:

     ```bash
     (gdb) catch throw
     ```

   - 捕获所有信号:

     ```bash
     (gdb) catch signal
     ```

   - 捕获特定信号(例如 SIGSEGV):

     ```bash
     (gdb) catch signal SIGSEGV
     ```

   - 捕获特定系统调用(例如 open):

     ```bash
     (gdb) catch syscall open
     ```

   - 捕获特定函数调用(例如 foo):

     ```bash
     (gdb) catch function foo
     ```

条件断点

b fn1 if ab:普通断点的条件设置
watch expr if cond:观察断点的条件设置

condition bnum expression:为 bnum 编号的断点添加或修改 expression 条件表达式
condition bnum:用于删除 bnum 编号断点的条件表达式,使其变成普通的无条件断点。

ignore bnum count: 设置某个断点的失效次数
enable [breakpoints] [count] count bnum_list:  设置某个断点的有效次数

断点维护命令

info b (info breakpoints) :显示当前程序的断点设置情况
disable 断点号n:暂停第n个断点,没有断点号,默认全部断点
enable 断点号n:开启第n个断点,没有断点号,默认全部断点
delete:删除所有类型和序号的断点
delete [断点号n1 断点号2 ···]:删除第n1 n2个断点
clear:清除当前位置所有普通的断点
clear 行号n:清除第n行的断点
注意:
delete 后面可以跟断点号,可以跟多个断点号
clear 后面跟行号,一次只能跟一个

?待确认
对指定类型的断点进行操作

程序执行

next:逐步调试
step:进入函数内部
until:next,但是在循环while for处执行,直接跳过循环体
until linenum: 直到运行第几行
jump linenum:从当前代码,直接跳到第几行,中间的代码不执行
finish: 快速执行完当前函数
return [val]: 直接从当前函数返回,可选是否设定函数的返回值
skip func:跳过某一函数。如果对某一个函数内部不感兴趣,可以通过skip跳过。
skip相关:
    info skip:查看skip信息
    skip delete:删除skip
    skip enable/disable: 打开或者关闭skip
continue: 运行到下一个断点
quit:结束gdb调试

查看文件和变量

**查看变量**
print :

(gdb) display <expression>:设置监视表达式  
(gdb) info display:显示已设置的监视表达式
(gdb) undisplay <display_number>:删除监视表达式
    其中 `<display_number>` 是要删除的监视表达式的编号。
(gdb) disable display <display_number>
(gdb) enable display <display_number>
    这将分别禁用或启用指定编号的监视表达式。
    
**查看源代码**
list :简记为 l ,其作用就是列出程序的源代码,默认每次显示10行。
list 行号:将显示当前文件以“行号”为中心的前后10行代码,如:list 12
list 函数名:将显示“函数名”所在函数的源代码,如:list main
list :不带参数,将接着上一次 list 命令的,输出下边的内容。
    
启动gdb时指定“`-tui`”参数(例如:`gdb -tui program`)
进入gdb后 layout src:查看源代码
         layout split:查看源代码和汇编代码
         Ctrl+X+A 退出layout

更改变量值

w u d

调试coredump

调试正在运行的程序:

上述参考自:

[GDB常用命令 - 知乎 (zhihu.com)]
[GDB break(b):设置断点 (biancheng.net)]
[GDB调试工具深入指南:从基础到高级 - 知乎 (zhihu.com)] [sourceware.org/gdb/current…]
[GDB 的 7 个单步调试命令 | Linux 中国 - 知乎 (zhihu.com)](skip 例子)

练习代码

#include<stdio.h>

int num(d) {
    int a = 2;
    return 2;
}

void bar(int i) {
    i = 4;
    printf("i = %d\n", i);
}

int main() {
    int d = 999;
    bar(num());
    int c = 0;
    return 0;
}
#include<stdio.h>
int main(int argc,char* argv[])
{
    int num = 1;
    while(num<100)
    {
        num *= 2;
    }
    printf("num=%d",num);
    return 0;
}