当前位置: 首页 > news >正文

gdb的使用与调试方法

CGDB 使用方法详解

CGDB可以理解成:

GDB 的终端图形界面版。

它不是另一套调试器,底层仍然是 GDB,只是在终端中增加了源码窗口、断点标记、当前执行行高亮和快捷键。上面通常显示源码,下面是标准 GDB 命令行;因此所有 GDB 命令在 CGDB 里仍然可以使用。CGDB

┌──────────────────────────────────────┐ │ 源码窗口:显示代码、当前执行行、断点 │ ├──────────────────────────────────────┤ │ GDB窗口:(gdb) 输入调试命令和看输出 │ └──────────────────────────────────────┘

一、安装 CGDB

Ubuntu 中执行:

sudo apt update sudo apt install cgdb gdb

检查:

cgdb --version gdb --version

CGDB 在 Ubuntu 软件仓库中属于基于 curses 的 GDB 界面。Ubuntu软件包


二、程序必须带调试信息

例如你的项目有:

client.c server.c com.c com.h

编译客户端:

gcc -Wall -Wextra -std=c11 -g -O0 \ client.c com.c -o client

编译服务端:

gcc -Wall -Wextra -std=c11 -g -O0 \ server.c com.c -o server

关键参数:

-g 在可执行文件中加入源码、变量、行号等调试信息 -O0 关闭优化,让代码执行顺序更接近源码

没有-g,CGDB 可能只能看到汇编,或者无法查看局部变量。优化开启后,还可能出现变量被优化掉、代码跳行等现象。GDB 官方建议编译时生成调试信息;关闭优化通常更容易逐行调试。Sourceware

Makefile :

CFLAGS = -Wall -Wextra -std=c11 -g -O0

三、启动 CGDB

调试服务端:

cgdb ./server

调试客户端:

cgdb ./client

进入后,通常会自动显示包含main()的源文件。

若没有显示想看的文件,在源码窗口按:

o

打开源码文件列表,然后选择client.cserver.ccom.c。源码窗口支持文件选择、搜索、跳转和可视化断点。CGDB


四、最重要:CGDB 有不同模式

CGDB 初学最容易混乱的地方就是“我现在在哪个窗口”。

1. 源码模式

启动后一般处于源码模式。

这里可以:

j / ↓ 向下移动 k / ↑ 向上移动 gg 跳到文件开头 G 跳到文件结尾 25G 跳到第25行 /内容 向下搜索 ?内容 向上搜索 n 下一个搜索结果 N 上一个搜索结果 空格 在当前行设置断点 t 设置临时断点 o 打开源码文件列表

2. GDB 命令模式

在源码模式按:

i

光标会进入下面的 GDB 窗口,现在可以输入:

break main run print i next continue

3. 返回源码模式

在 GDB 命令窗口按:

Esc

回到上方源码窗口。

因此最核心的切换是:

源码窗口 --按 i--> GDB命令窗口 GDB窗口 --按 Esc--> 源码窗口

4. GDB 输出滚动模式

GDB 输出很多时,在 GDB 窗口按PageUp会进入历史输出滚动模式。

滚动时:

PageUp / Ctrl-u 向上 PageDown / Ctrl-d 向下 gg 最前面 G 最后面 q / Enter / i 退出滚动模式

这些模式和按键均来自 CGDB 的官方模式设计。CGDB


五、第一次完整调试流程

假设调试:

cgdb ./client

第一步:在main()设置断点

在源码窗口移动到:

int main()

或者函数内第一条有效语句,然后按:

空格

断点行旁边会出现断点标记。

也可以按i进入 GDB 窗口,输入:

break main

简写:

b main

第二步:启动程序

源码模式按:

F5

等价于:

run

简写:

r

程序运行到断点前停止,源码窗口会高亮当前即将执行的行。

第三步:查看变量

i,输入:

print i

简写:

p i

查看指针:

p addr

十六进制显示:

p/x addr

查看指针指向的字符:

p *addr

查看第二个字节:

p addr[1]

查看第二个字节地址:

p &addr[1]

第四步:单步执行

Esc回源码窗口,然后使用快捷键:

F8 next:执行下一行,不进入函数 F10 step:执行下一行,遇到函数则进入函数 F7 finish:执行完当前函数,返回调用者 F6 continue:继续运行到下一个断点

官方默认快捷键对应:

F5 run F6 continue F7 finish F8 next F10 step

六、next 和 step的区别

假设当前行:

int shmid = create_shm(SHM_SIZE);

执行:

next

会把整个create_shm()当成一行执行完,不进入函数内部。

执行:

step

会进入:

int create_shm(size_t size) { ... }

常用简写:

n next s step fin finish c continue

注意:在源码模式直接按字母s,它不是 GDB 的step命令,而是切换到 GDB 输出滚动模式。因此初学阶段建议使用F10,或者先按i再输入s


七、程序执行控制命令

命令作用
run/r从头启动程序
start启动并自动停在main()
continue/c继续到下一个断点
next/n下一源码行,不进入函数
step/s下一源码行,进入函数
finish运行到当前函数返回
until运行到循环后面或指定行
kill终止当前被调试程序
quit/q退出调试器

例如:

start

会直接启动并停在main()附近,比先设置break mainrun更方便。

程序带命令行参数时:

set args hello 123 show args run

相当于正常运行:

./client hello 123

八、断点详解

1. 按函数名设置

break main break create_shm break attach_shm

2. 按行号设置

当前文件第 25 行:

break 25或者 b 25

指定文件:

break client.c:25 break com.c:15

3. 条件断点

例如只在i == 80时停止:

break client.c:30 if i == 80

也可以先设置普通断点:

break client.c:30

假设编号为 2,再添加条件:

condition 2 i == 80

4. 查看所有断点

info breakpoints

简写:

info b

GDB 会给每个断点编号,并显示是否启用、地址、源码位置和条件。Sourceware

5. 禁用和启用

disable 2 enable 2

禁用不会删除断点,只是暂时不生效。

6. 删除断点

删除编号 2:

delete 2

删除全部:

delete

按源码位置删除:

clear client.c:30

7. 临时断点

tbreak main

临时断点命中一次后自动删除。


九、查看变量和表达式

print

p i p shmid p addr p addr[0] p addr[1] p strlen(addr) p sizeof(addr)

格式化显示:

p/x i 十六进制 p/d i 十进制 p/c i 字符 p/t i 二进制

例如:

p/c 65

结果类似:

65 'A'

查看变量类型

ptype addr ptype shmid

例如:

ptype addr

可能显示:

type = char *

查看当前函数局部变量

info locals

查看当前函数参数

info args

自动显示变量

display i display addr

以后每次程序停止,GDB 都会自动显示它。

查看自动显示列表:

info display

取消:

undisplay 1

临时修改变量

set variable i = 90

简写通常也可以:

set var i = 90

这只修改当前调试进程运行时的变量,不会修改源代码文件。


十、查看内存:x命令

x表示 examine,专门查看内存。

格式:

x/数量格式单位 地址

可以理解为:

x / n f u address n:查看多少个单位 f:以什么格式显示 u:每个单位多大

常见格式:

x 十六进制 d 有符号十进制 u 无符号十进制 c 字符 s 字符串 i 汇编指令

常见单位:

b 1字节 h 2字节 w 4字节 g 8字节

GDB 官方将x定义为独立于程序数据类型的内存查看命令。Sourceware

查看共享内存中的字符串

x/s addr

查看 32 个字节的十六进制值

x/32bx addr

含义:

32:查看32个 b :每个1字节 x :十六进制

查看 64 个字符

x/64cb addr

查看 10 个整数

假设pint *

x/10dw p

查看指令

x/10i $pc

从当前程序计数器开始查看 10 条机器指令。


十一、特别适合你当前共享内存代码的调试方法

你之前有:

char *addr = attach_shm(shmid); while (i <= 90) { snprintf(addr, SHM_SIZE, "%c", i); addr += 2; }

可以在循环内部设置断点,然后查看:

p/x addr p i x/16cb addr

如果保存了原始地址:

char *base = addr;

可以查看移动了多少字节:

p addr - base

例如输出:

$1 = 20

说明addr已经向后移动了 20 字节。

查看整个共享内存开头:

x/64cb base

查看字符串:

x/s base

循环结束前检查:

p/x base p/x addr p addr - base

这样可以直接证明:

base 仍是 shmat() 返回的起始地址 addr 已经因为 addr += 2 向后移动

最后必须:

detach_shm(base);

而不是:

detach_shm(addr);

十二、查看函数调用栈

程序崩溃或卡住时,最重要的命令是:

backtrace

简写:

bt

输出可能类似:

#0 commshm() at com.c:15 #1 create_shm() at com.c:6 #2 main() at server.c:8

意思是:

main() └── create_shm() └── commshm() 当前停在这里

显示局部变量:

bt full

切换栈帧:

frame 0 frame 1 frame 2

向调用者移动:

up

向被调用函数移动:

down

调用栈由一系列栈帧组成,GDB 可以查看每层函数的参数、局部变量和源码位置。Sourceware


十三、调试段错误

程序出现:

Segmentation fault

在 CGDB 中重新运行:

run

发生段错误后通常会自动停住,然后按顺序执行:

bt frame 0 info locals info args list p 相关指针 x/16bx 相关指针

例如:

p addr p/x addr x/16bx addr

如果地址是:

0x0

通常说明空指针。

还可以检查:

p shmid p addr == (void *)-1

调试shmat()时尤其有用。


十四、监视变量什么时候被修改

例如想知道addr什么时候变化:

watch addr

程序继续运行:

continue

addr += 2修改addr时,GDB 会停止,并显示旧值和新值。

监视共享内存第一个字节:

watch base[0]

监视i

watch i

查看监视点:

info breakpoints

删除方式与普通断点相同:

delete 3

Watchpoint 是一种在表达式值发生变化时停止程序的特殊断点;某些平台使用硬件监视点,软件监视点则可能明显降低执行速度。Sourceware

对于你的共享内存实验,最好在实际执行写操作的客户端进程中设置监视点;服务端和客户端是两个独立进程,通常应分别调试。


十五、调试客户端和服务端

clientserver是两个独立可执行程序,最简单可靠的方法是使用两个 CGDB。

终端一

cgdb ./server

设置断点:

break main break server.c:读取数据的行号 run

终端二

cgdb ./client

设置断点:

break main break client.c:写共享内存的行号 run

终端三

继续监视进程:

watch -n 1 \ 'ps -o pid,ppid,pgid,sid,stat,wchan:25,cmd -C client -C server'

这样可以同时观察:

服务端停在哪里 客户端停在哪里 共享内存内容如何变化 进程当前是否睡眠或运行

十六、附加到已经运行的进程

假设服务端已经运行:

./server

另一个终端查询 PID:

pgrep -x server

假设结果:

1281513

打开 CGDB:

cgdb ./server

i,输入:

attach 1281513

附加后,GDB 会先暂停该进程。接下来可以:

bt info locals p addr continue

完成后:

detach

detach会解除调试控制,并让进程继续独立运行。GDB 官方支持通过 PID 附加到已运行进程;附加时会先停止该进程,随后可以设置断点、单步和查看变量。Sourceware

这个方法特别适合判断:

服务端到底阻塞在read()sleep()open(),还是别的位置。

附加后执行:

bt

就能看到当前调用链。


十七、调试fork()父子进程

如果程序内部调用fork(),想让调试器跟踪子进程:

set follow-fork-mode child

想继续跟踪父进程:

set follow-fork-mode parent

希望父子进程都保留在 GDB 控制下:

set detach-on-fork off

查看所有被调试进程:

info inferiors

切换到第二个进程:

inferior 2

恢复默认的“分离另一个进程”模式:

set detach-on-fork on

GDB 在 Linux 上支持通过follow-fork-mode选择父进程或子进程,并通过detach-on-fork off同时保留多个 fork 产生的进程。Sourceware


十八、调试系统调用

你正在学习管道、共享内存,可以让 GDB 在系统调用发生时停止。

捕获read()

catch syscall read

捕获write()

catch syscall write

同时捕获:

catch syscall read write

捕获 System V 共享内存相关调用:

catch syscall shmget shmat shmdt shmctl

查看捕获点:

info breakpoints

继续:

continue

注意,这可能会非常频繁地停止,因为标准库和动态链接器也可能执行很多系统调用。GDB 的catch syscall可以根据系统调用名称或编号创建捕获点,具体可用名称取决于目标系统和 GDB 的系统调用数据库。Sourceware


十九、调试命名管道中的SIGPIPE

如果写端向已经没有读端的管道写入,程序可能收到SIGPIPE

让 GDB 收到SIGPIPE时停住:

handle SIGPIPE stop print pass

含义:

stop 收到信号时停止 print 显示提示 pass 继续时仍把信号交给程序

查看信号配置:

info signals SIGPIPE

GDB 可以配置不同信号是停止、打印、传递还是忽略;SIGPIPE在 Unix 系统中是标准信号之一。Sourceware


二十、程序输入输出和 CGDB 命令冲突

假如被调试程序需要:

scanf(...) read(STDIN_FILENO, ...)

程序输入和 GDB 命令可能都在同一个终端,看起来比较乱。

对于你的 SSH 环境,建议给被调试程序指定另一个终端。

在另一个终端执行:

tty

假设输出:

/dev/pts/5

在 CGDB 的 GDB 窗口执行:

set inferior-tty /dev/pts/5

然后:

run

此时:

CGDB窗口:输入调试命令 /dev/pts/5:显示程序输出、接收程序输入

查看当前设置:

show inferior-tty

GDB 官方支持通过set inferior-tty将被调试程序的输入输出定向到指定终端。Sourceware

CGDB 源码模式还提供Ctrl-T打开新的被调试程序终端,不过在纯 SSH 环境中,手动指定/dev/pts/N往往更稳定。CGDB


二十一、窗口快捷键

在源码模式中:

快捷键作用
Ctrl-W横向/纵向切换窗口
-缩小源码窗口一点
=放大源码窗口一点
_缩小源码窗口约 25%
+放大源码窗口约 25%
Ctrl-L清屏并重新绘制
'.跳回当前执行行
o打开源码文件列表

这些是 CGDB 自身快捷键,不是 GDB 命令。CGDB


二十二、配置 CGDB

配置文件默认是:

~/.cgdb/cgdbrc

创建:

mkdir -p ~/.cgdb nano ~/.cgdb/cgdbrc

推荐配置:

set autosourcereload set color set hlsearch set ignorecase set tabstop=4 set winsplitorientation=horizontal set winsplit=src_big

含义:

autosourcereload 源文件修改后自动重新加载 color 开启颜色 hlsearch 高亮搜索结果 ignorecase 搜索时忽略大小写 tabstop=4 Tab显示为4个空格 winsplitorientation 源码和GDB上下排列 winsplit=src_big 源码窗口稍大

也可以改成左右布局:

set winsplitorientation=vertical

CGDB 默认把用户配置、历史和日志放在~/.cgdb/,启动时会读取其中的cgdbrc;窗口布局、搜索、颜色、Tab 宽度等均可配置。CGDB

临时设置时,在源码模式输入:

:set winsplitorientation=vertical

配置文件中则直接写:

set winsplitorientation=vertical

二十三、常见问题

1. 看不到源码

重新编译:

gcc -g -O0 main.c -o main cgdb ./main

确认启动的是可执行文件,不是源码:

cgdb ./main

不是:

cgdb main.c

2. 变量显示<optimized out>

关闭优化:

gcc -g -O0 main.c -o main

3. 显示No symbol "addr" in current context

可能原因:

当前还没执行到 addr 的作用域 当前栈帧不是定义 addr 的函数 程序没有使用 -g 编译 编译器把变量优化掉了

先执行:

bt frame 0 info locals

4. 程序正在运行,不能输入命令

按:

Ctrl-C

这会中断被调试程序,让控制权回到 GDB。

注意这里终止的是程序当前运行,不一定退出 CGDB。

5. 终端突然“冻住”

可能误按了:

Ctrl-S

按:

Ctrl-Q

恢复。

然后输入等价 GDB 命令:

run next step continue finish

二十四、命令快查

i 进入GDB命令窗口 Esc 回到源码窗口 空格 设置源码断点 start 启动并停在main run / r 从头运行 continue / c 继续运行 next / n 下一行,不进函数 step / s 下一行,进入函数 finish 跳出当前函数 break / b 设置断点 info breakpoints 查看断点 delete 删除断点 print / p 查看变量 info locals 查看局部变量 display 每次停止自动显示变量 watch 变量变化时停止 x/32bx addr 查看32字节十六进制内存 x/s addr 按字符串查看内存 bt 查看调用栈 frame N 切换栈帧 up / down 上下切换栈帧 quit / q 退出
http://www.jsqmd.com/news/1337577/

相关文章:

  • 总结 8.05
  • 2026 年现阶段苍南比较好的打捞队怎么收费制造厂家哪个好,别再被坑了!那些藏在水下打捞里的收费套路,你真的看懂了?-钱途潜水打捞公司 - 企业信息推荐-2
  • rust syn是否类似于go的ast
  • 太仓有名的液冷数据中心管路自动焊优质厂商2026怎么选 - 品牌优推
  • 营口水下作业/水下封堵公司本地水下施工队哪家靠谱 - 行业推荐【认证官】
  • 2026 年 7 月新发布:平山正规的无人机用G657A2光纤实力厂家哪家可靠,无人机续航翻3倍?这款特殊光纤藏着不为人知的秘密 - 鉴选官
  • UG/NX二次开发中PK_BODY_boolean_2布尔运算的实战避坑指南
  • Python排序函数详解:sort()、sorted()与reversed()的核心原理与实战应用
  • 信息量爆炸[特殊字符]华为8.5发布会新品全梳理
  • 9.11. 将线性设备转换为 RAID 逻辑卷
  • ACOLITE大气校正完整指南:3步掌握卫星遥感数据处理核心技术
  • 选山东体系认证公司看这里如何快速合规拿证 - 品牌优推
  • 深度解析邢台建设局网站如何赋能城市数字化转型与便民办事体验提升
  • 2026 年新消息:蓝山专业的农村自建房钢网销售厂家哪个好,用这玩意儿搭自建房框架,居然比传统工艺省一半工时还更结实-整建整装 - 行业推荐官【认证】
  • 苏州优秀的防爆布袋除尘器公司怎么选?看这几点就懂了 - 品牌优推
  • 2026 年更新:合肥可靠的Q345B无缝钢管厂家联系电话,施工时选错钢材,居然差点让工程停工?这玩意儿才是大厂都悄悄用的抗压利器?-中拓兴耀无缝钢管 - 企业推荐管【认证】
  • 2026 年黄石靠谱的铲车租赁厂家怎么联系,铲车不用买靠它省了二十万,还避开了场地维护的麻烦 - 行业推荐官-2
  • AI辅助设计实战:用Claude打造项目进度管理表界面
  • Transformer时间动态机制:从残差流到长上下文优化的核心原理与实践
  • eNSP实验详解:PPP协议与CHAP认证配置及排错指南
  • 2026 年鼓楼靠谱的水下检查实力厂家哪家好,船底藏着的隐患竟藏得这么深?没人下水前绝对不会发现-救援打捞 - 行业推荐官【认证】
  • 如何轻松下载B站大会员专属4K视频?这个开源工具让你永久保存心爱内容
  • Oracle数据库官网下载全攻略:从版本选择到安装避坑指南
  • 从零制作《绝区零》蕾米埃尔MMD动画:全流程实践与问题排查指南
  • DAY15 构造数据类型与位运算
  • Unity智能阴影优化:从性能黑洞到按需渲染的实战方案
  • 乐山正规翻新喷漆、彩钢棚搭建与灯箱广告公司怎么选?2026年本地服务商综合参考 - 优质品牌商家
  • 高端工业防腐涂料厂家该怎么选?2026年无溶剂与耐候型涂料企业综合观察 - 优质品牌商家
  • 2026 年新发布:徐州诚信的融合餐厅洗碗机生产厂家哪个好,别再硬扛餐厅洗碗了,它才是后厨效率翻番的秘密武器。-东泰洗碗机 - 行业推荐官[官方】--
  • 数理统计核心概念:从样本推断总体的方法论与三大抽样分布