【Linux】Linux环境基础开辟工具利用之Linux调试器-gdb利用

[复制链接]
发表于 2026-10-3 15:59:56 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×

先分清:debug 模式与 release 模式

程序有两种发布方式,debug(调试)模式和 release(发布)模式,它们的定位完全不同。

debug 模式

  • 目的:用于开发和测试阶段,让开发者更容易地调试和跟踪程序里的 bug,确保发布前没有大问题。
  • 特性:编译时不做过多优化,方便 GDB 这类工具观察程序状态(变量值、函数调用栈等);包含详细的调试信息(符号表);运行时可能带额外检查(数组越界、空指针等);因为没优化还要带调试信息,通常跑得慢。

release 模式

  • 目的:部署到生产环境,给用户稳定的体验。
  • 特性:编译时做各类优化(代码重排、循环展开、函数内联等)来提速;不带调试信息(符号表),可执行文件更小、加载更快;移除运行时检查以减少开销;跑得快。

Linux 默认是 release 模式

用 gcc/g++ 编出来的二进制默认是 release,里面没有调试信息,gdb 直接上会报"没有调试符号"。要用 gdb 调试,编译时必须加 -g 选项。

怎么验证?两条路:

  1. 先用裸 gcc Test.c 生成 a.out,gdb 进去会看到"无调试信息"的提示;再 gcc -g Test.c 重新生成,同样的 gdb 提示就没了。
  2. 看体积:-g 编出来的文件明显更大,多出来的部分就是调试信息。

更严谨的办法是用 readelf 直接检查 ELF 文件(Linux 可执行文件的标准格式)里的调试段:

readelf -S a.out | grep debug          # release 版通常看不到 debug 段
gcc -g Test.c -o test_dbg
readelf -S test_dbg | grep debug       # debug 版能看到 .debug_info 等段

再补一条实战建议:调试时用 gcc -g -O0。-O0 关掉优化,源码顺序和机器执行顺序一一对应,断点跳来跳去的情况最少;开着 -O2 调试经常出现"这一行还没执行变量就变了"的诡异现象。

gdb 基本用法

进入调试:gdb 文件名。下面按使用频率把常用命令列一遍。

看代码

(gdb) list / l 行号        # 从指定行开始往下显示源码,每次 10 行;不带行号则按上下文续
(gdb) list / l 函数名      # 显示某个函数的源码
(gdb) info line 行号       # 某行在编译后的地址范围

断点

(gdb) break / b 行号       # 在某行打断点
(gdb) break 函数名          # 在函数开头打断点
(gdb) info breakpoints      # 查看所有断点
(gdb) disable breakpoints n # 禁用序号为 n 的断点
(gdb) enable breakpoints n  # 启用序号为 n 的断点
(gdb) delete / d breakpoints n  # 删除序号 n 的断点
(gdb) delete breakpoints    # 删除全部断点
注意断点序号:断点的编号是线性递增的,只会越来越大。删掉 3 号再打新断点会得到 5 号、6 号,绝不会复用已经删掉的 3 号。

跑起来

(gdb) run / r               # 从头运行;有断点就停在断点处
(gdb) start                 # 停在 main 第一行,先别急着跑完
(gdb) continue / c          # 继续跑到下一个断点、程序结束或异常
(gdb) until 行号            # 运行到第 n 行停下
(gdb) finish                # 执行到当前函数返回后停下
(gdb) next / n              # 单步:执行下一行;若该行是函数调用,直接把结果显示出来,不进函数
(gdb) step / s              # 单步:执行下一行;若该行是函数调用,进到函数内部逐行跑
(gdb) quit / q              # 退出 gdb

n 与 s 的区别是面试和调试里最常被问的:一个"跳过函数"、一个"走进函数"。想看某个函数的内部逻辑就用 s,只想确认它返回了啥就用 n。

看数据

(gdb) print / p 变量        # 打印变量值
(gdb) p 表达式              # 可以算表达式,也能调用函数
(gdb) set var 变量=值       # 修改变量的值(用来复现 bug 很顺手)
(gdb) display 变量名        # 跟踪变量,每次停下来都自动显示
(gdb) undisplay n           # 取消对序号 n 的跟踪
(gdb) info locals           # 看当前栈帧里的局部变量
(gdb) x /nfu 地址           # 按格式看内存,如 x/10c buf 看 10 个字符

看调用栈

(gdb) backtrace / bt        # 各级函数调用及参数(查看崩溃时是怎么一路调过来的)
(gdb) bt full               # 更完整,含局部变量
(gdb) frame 帧号            # 切到指定栈帧
(gdb) up / down             # 往上/往下翻栈帧

排查段错误(Segmentation fault)时,bt 基本是第一步:看栈的最顶层是哪个函数、哪个地址,再结合 info locals 和 x 看当时的数据。

动态观察点

(gdb) watch 变量            # 变量被写时停下(硬件观察点)
(gdb) rwatch 变量           # 变量被读时停下
(gdb) awatch 变量           # 读写都停

适合"某个值莫名其妙被改了"这种场景——与其到处打断点猜,不如直接盯住它。

命令行参数与 core

(gdb) set args 参数1 参数2   # 给被调程序传参
(gdb) run 参数1 参数2        # 一起给也行
(gdb) gdb ./app core         # 直接拿 core 文件进去看崩溃现场

core 调试的前提是系统允许生成 core:ulimit -c 不能是 0,kernel.core_pattern 也要指向可写位置。线上服务一般默认关掉,排查崩溃时要先打开。

一个完整调试流程示例

$ gcc -g -O0 myprog.c -o myprog
$ gdb ./myprog
(gdb) b main                # 在 main 打断点
(gdb) r                     # 跑起来
(gdb) l                     # 看当前位置的源码
(gdb) n                     # 一行一行走
(gdb) s                     # 想进函数内部就用 s
(gdb) p argc                # 看变量
(gdb) display argc          # 挂上跟踪,之后每次停都显示
(gdb) bt                    # 走到一半想看调用链
(gdb) c                     # 继续
(gdb) q                     # 退出

常见踩坑

  • 提示 "No symbol table info available":忘了 -g,重新编译再进 gdb。
  • 断点打不上 / 行号对不上:源码文件和编译时的那份不一致(比如代码改过但二进制是旧的), gdb 定位的行会漂移。调试前先确认二进制是最新编的。
  • 库函数没有符号:调试依赖库时,对应库也要带调试符号(发行版一般提供 -dbgsym 或 -debuginfo 包)。
  • run 不起来:程序会读 stdin/argv,卡住时先 set args 或 set stdin /dev/null。
  • 多线程程序默认跟到主线程:可以用 thread apply all bt 一次性看所有线程的栈,很实用。

小结

gdb 的使用分四块:看代码(list)、控流程(b 打点、r 运行、n/s 单步、c 继续、until/finish)、查数据(p、display、x、watch)、看调用栈(bt、frame)。

前提是编译时带 -g(建议 -g -O0),并且调试的二进制与源码版本一致。掌握这套命令,段错误、越界、野指针这类问题就有了最直接的定位手段——比满屏打日志日志高效得多。

(本文由 qidao123.com企服评测-应用市场 编辑提示整理:示例基于 GNU gdb 与 gcc,适用于 Ubuntu / Debian / CentOS 等 Linux 环境,命令行已在标准编译流程中验证。)

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表