Linux:调试器-gdb/cgdb使用

1 示例代码

objectivec 复制代码
#include <stdio.h>

int Sum(int s, int e)
{
    int result = 0;
    for(int i = s; i <= e; ++i)
    {   
        result += i;
    }   

    return result;
}

int main()
{
    int start = 1;
    int end = 100;
    printf("I will begin\n");
    int n = Sum(start, end);
    printf("running done, result is: [%d-%d]=%d\n", start, end, n); 
    while(1)
    {   
        printf("我是一个进程\n");
    }   

    return 0;
}

2 预备知识

程序的发布方式有两种,debug 模式和 release 模式,Liunx gcc/g++ 出来的二进制程序,默认是 release 模式。

要是 gdb 和 cgdb 调试,必须在源代码生成二进制程序的时候,加上 -g 选项,如果没有添加,程序无法被编译。

bash 复制代码
~/mydir/linux/gdb_tools$ gcc -o code code.c    # 默认 release 版本,不支持调试
~/mydir/linux/gdb_tools$ file code
code: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=913822b416c73e5294e4b424d8c4f04ea9b42c1e, for GNU/Linux 3.2.0, not stripped


~/mydir/linux/gdb_tools$ gcc -o code.exe code.c -g    # debug 版本,支持调试
code.exe: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=770c3ba5aa1d5c7c996be9c7944cba0c6bb9f263, for GNU/Linux 3.2.0, with debug_info, not stripped

3 常见使用

开始:

bash 复制代码
gdb 可执行程序    # 一般我们不这么用
cgdb 可执行程序   # 一般我们用cgdb

退出:

bash 复制代码
ctrl + d 或者 quit 

|--------------------|-----------------------|-------------------------|
| 命令 | 作⽤ | 样例 |
| list/l | 显⽰源代码,从上次位置开始,每次列出10⾏ | list/l 10 |
| list/l 函数名 | 列出指定函数的源代码 | list/l main |
| list/l ⽂件名:⾏号 | 列出指定⽂件的源代码 | list/l mycmd.c:1 |
| r/run | 从程序开始连续执⾏ | run |
| n/next | 单步执⾏,不进⼊函数内部 | next |
| s/step | 单步执⾏,进⼊函数内部 | step |
| break/b [⽂件名:]⾏号 | 在指定⾏号设置断点 | break 10break test.c:10 |
| break/b 函数名 | 在函数开头设置断点 | break main |
| info break/b | 查看当前所有断点的信息 | info break |
| finish | 执⾏到当前函数返回,然后停⽌ | finish |

|------------------------|-------------------|----------------------|
| print/p 表达式 | 打印表达式的值 | print start+end |
| p 变量 | 打印指定变量的值 | p x |
| set var 变量=值 | 修改变量的值 | set var i=10 |
| continue/c | 从当前位置开始连续执⾏程序 | continue |
| delete/d breakpoints | 删除所有断点 | delete breakpoints |
| delete/d breakpoints n | 删除序号为n的断点 | delete breakpoints 1 |
| disable breakpoints | 禁⽤所有断点 | disable breakpoints |
| enable breakpoints | 启⽤所有断点 | enable breakpoints |
| info/i breakpoints | 查看当前设置的断点列表 | info breakpoints |
| display 变量名 | 跟踪显⽰指定变量的值(每次停⽌时 | display x |
| undisplay 编号 | 取消对指定编号的变量的跟踪显⽰ | undisplay 1 |
| until X⾏号 | 执⾏到指定⾏号 | until 20 |
| backtrace/bt | 查看当前执⾏栈的各级函数调⽤及参数 | backtrace |
| info/i locals | 查看当前栈帧的局部变量值 | info locals |
| quit | 退出GDB调试器 | quit |

gdb 调试效果(模式不太友好):

cgdb 调试效果:代码和调试界面上下分开,比较方便

3.1 打断点: 对应的行号会高亮

**3.2 运行:**r 命令会从当前的断点开始运行

**3.3 单步运行:**s 会进入具体的函数步骤

**3.4 逐过程运行:**n 会跳过相应函数

**3.5 查看断点:**info b

**3.6 查看变量:**display 变量名

**3.7 取消查看变量:**undisplay 变量名号,undisplay 1 这时就看不到 result

**3.8 监视一个变量:**watch 变量名

**3.9 跳转到指定行:**until 行号(前提中间没有断点)

3.10 从当前行开始连续执行程序: c在断点之间连续执行

**3.11 执行到当前函数返回,然后停止:**finish(前提是中间没有断点,要不然会跳到断点处)

3.12 查看栈帧:bt

**3.13 查看当前当前栈帧局部变量值:**i locals

**3.14 禁用断点:**disable 断点编号,禁用的断点hui'bia

**3.15 启用断点:**enable 断点编号

**3.16 设置临时变量值:set var 变量名=num,**方便调试是否这个变量导致的问题

3.17 打条件断点:b 行号 if 变量名==num

3.18 在已有断点的情况下新增、修改条件:condition 断点编号 变量名==num

相关推荐
oMcLin17 小时前
如何在 Rocky Linux 8.7 上通过 Prometheus 与 Grafana 结合,提升大规模容器环境的监控与性能分析?
linux·grafana·prometheus
带土117 小时前
4. C++ static关键字
开发语言·c++
橘颂TA17 小时前
【Linux】死锁四条件的底层逻辑:从锁冲突到 STL 组件的线程安全实践(Ⅵ)
linux·运维·服务器·c++·死锁
埃伊蟹黄面17 小时前
ELF深入解剖:从文件头到动态段,图解库的二进制构成
linux·c·
C++ 老炮儿的技术栈17 小时前
什么是通信规约
开发语言·数据结构·c++·windows·算法·安全·链表
五仁火烧18 小时前
生产环境中配置了接口3000后,不能启动,改成8080后就可以
linux·网络·安全·vue
JiMoKuangXiangQu18 小时前
Linux build:头文件安装
linux·headers_install
lbb 小魔仙18 小时前
【Linux】云原生运维效率提升:Linux 终端工具链(kubectl + tmux + fzf)组合拳教程
linux·运维·云原生
清水白石00818 小时前
解构异步编程的两种哲学:从 asyncio 到 Trio,理解 Nursery 的魔力
运维·服务器·数据库·python
码农小韩19 小时前
基于Linux的C++学习——动态数组容器vector
linux·c语言·开发语言·数据结构·c++·单片机·学习