如何用GCC在Linux下调试程序,轻松排查问题,成为编程高手?
- 内容介绍
- 文章标签
- 相关推荐
一、为什么你需要在 Linux 下用 GCC 调试?
在实际开发中。你可能会遇到以下让人抓狂的痛点:
- 程序运行时莫名崩溃,却找不到堆栈信息。
- 变量的值总是和预期不符,调试过程像盲人摸象。
- 代码执行慢得像龟速,却不知道瓶颈到底在哪里。说起来,
- 每次修改一点代码。 都要重新编译、重新跑,效率低下。
掌握 GCC 与 GDB 的调试技巧。能够快速定位这些问题,让你从“纠错小白”升级为“编程高手”。
二、准备工作:安装 GCC 与 GDB
大多数 Linux 发行版默认已提供 GCC 与 GDB。若程序中缺失,只需执行:
sudo apt-get update
sudo apt-get install build-essential gdb # Debian/Ubuntu 系列
# 或者
sudo yum groupinstall "Development Tools" gdb # RHEL/CentOS 系列
三、编译时加入调试信息
只有在可执行文件中嵌入调试符号。GDB 才能映射源码行号和变量名。
# 基本编译命令
gcc -g -Wall -O0 -o myprogram myprogram.c
# 常用选项说明
-g # 生成调试信息
-Wall # 开启所有警告,帮助提前发现潜在错误
-O0 # 关闭调整。避免代码与源码行号不对应
四、启动 GDB 并加载程序
# 启动调试器
gdb ./myprogram
# 进入 GDB 后常见提示:
4.1 常用启动参数
-
gdb -q myprogram静默模式,不显示版权信息。 -
gdb -ex "set pagination off" -ex "run"一次性运行并关闭分页。
五、基本调试流程概览
- 设置断点让程序在关键位置停下来。
- 运行程序从入口开始执行。
- 单步执行逐行或逐过程观察行为。
- 检查状态查看变量、寄存器、调用栈。
- 修改变量在不中止程序的情况下纠正错误数据。
- 继续执行或退出.
六、断点的高级使用技巧
6.1 按函数名或行号设置断点
break main # 在 main 函数入口处暂停
break 42 # 在第 42 行暂停
break myfunc if x>10 # 条件断点,仅当 x 大于 10 时触发
6.2 临时断点与删除断点
tbreak foo # 临时断点。触发一次后自动删除
delete 3 # 删除编号为 3 的断点
clear myfile.c:25 # 删除指定文件行的所有断点
七、单步执行与流程控制
| 命令 | 作用说明 |
|---|---|
s or step | 进入函数内部,逐语句执行;按理说,适合细致跟踪调用链。 |
n or next | 跳过当前函数的内部实现,直接到下一行;防止进入库函数内部干扰视线。 |
C or continue | 继续运行直到下一个断点或程序结束。不过, |
八、检查程序状态——变量、寄存器与调用栈
a. 查看变量值
print i # 打印整型变量 i 的当前值
p/x ptr # 十六进制显示指针 ptr
display counter # 每次停下来自动显示 counter 的值
b. 查看局部/全局符号表
info locals # 列出当前栈帧的局部变量及其值
info globals # 列出全局符号表
backtrace # 简要显示所有栈帧
bt full # 完整信息。包括每帧的局部变量值
frame 2 # 切换到第 2 帧进行深入检查
d. 检查寄存器状态
info registers # 打印所有通用寄存器及其当前内容
info registers eax # 查看特定寄存器 eax 的值
九、动态修改变量——现场修复错误
# 将全局计数器重置为 0,免得每次重启都要改源码再编译。set variable counter = 0
# 改变指针指向,以验证内存越界是否导致崩溃。set $rax = 0x601050
十、性能分析与慢速排查
info registers # 打印所有通用寄存器及其当前内容
info registers eax # 查看特定寄存器 eax 的值
# 将全局计数器重置为 0,免得每次重启都要改源码再编译。set variable counter = 0
# 改变指针指向,以验证内存越界是否导致崩溃。set $rax = 0x601050
If your program feels sluggish。you can use GDB’s built‑in TUI mode + perf integration.
| 工具/命令 | 用途及示例 |
|---|---|
| `record` | P记录程序执行过程,可回放查看每一步耗时。至于示例,record start continue record stop record replay |
| `info line *addr` | `addr` 为机器码地址。可定位热点代码所在源文件行号。示例这方面,info line *0x4005f6 |
| `thread apply all bt` | D在多线程环境下一次性打印全部线程栈。帮助定位竞争条件,从示例来看,thread apply all bt |
| `monitor reset` | K使用硬件仿真网站时可快速复位目标板。说到示例,monitor reset |
| `set pagination off` | S关闭分页。让大量输出一次性展示,更适合脚本化分析。说到示例,set pagination off |
|
|---|
一、为什么你需要在 Linux 下用 GCC 调试?
在实际开发中。你可能会遇到以下让人抓狂的痛点:
- 程序运行时莫名崩溃,却找不到堆栈信息。
- 变量的值总是和预期不符,调试过程像盲人摸象。
- 代码执行慢得像龟速,却不知道瓶颈到底在哪里。说起来,
- 每次修改一点代码。 都要重新编译、重新跑,效率低下。
掌握 GCC 与 GDB 的调试技巧。能够快速定位这些问题,让你从“纠错小白”升级为“编程高手”。
二、准备工作:安装 GCC 与 GDB
大多数 Linux 发行版默认已提供 GCC 与 GDB。若程序中缺失,只需执行:
sudo apt-get update
sudo apt-get install build-essential gdb # Debian/Ubuntu 系列
# 或者
sudo yum groupinstall "Development Tools" gdb # RHEL/CentOS 系列
三、编译时加入调试信息
只有在可执行文件中嵌入调试符号。GDB 才能映射源码行号和变量名。
# 基本编译命令
gcc -g -Wall -O0 -o myprogram myprogram.c
# 常用选项说明
-g # 生成调试信息
-Wall # 开启所有警告,帮助提前发现潜在错误
-O0 # 关闭调整。避免代码与源码行号不对应
四、启动 GDB 并加载程序
# 启动调试器
gdb ./myprogram
# 进入 GDB 后常见提示:
4.1 常用启动参数
-
gdb -q myprogram静默模式,不显示版权信息。 -
gdb -ex "set pagination off" -ex "run"一次性运行并关闭分页。
五、基本调试流程概览
- 设置断点让程序在关键位置停下来。
- 运行程序从入口开始执行。
- 单步执行逐行或逐过程观察行为。
- 检查状态查看变量、寄存器、调用栈。
- 修改变量在不中止程序的情况下纠正错误数据。
- 继续执行或退出.
六、断点的高级使用技巧
6.1 按函数名或行号设置断点
break main # 在 main 函数入口处暂停
break 42 # 在第 42 行暂停
break myfunc if x>10 # 条件断点,仅当 x 大于 10 时触发
6.2 临时断点与删除断点
tbreak foo # 临时断点。触发一次后自动删除
delete 3 # 删除编号为 3 的断点
clear myfile.c:25 # 删除指定文件行的所有断点
七、单步执行与流程控制
| 命令 | 作用说明 |
|---|---|
s or step | 进入函数内部,逐语句执行;按理说,适合细致跟踪调用链。 |
n or next | 跳过当前函数的内部实现,直接到下一行;防止进入库函数内部干扰视线。 |
C or continue | 继续运行直到下一个断点或程序结束。不过, |
八、检查程序状态——变量、寄存器与调用栈
a. 查看变量值
print i # 打印整型变量 i 的当前值
p/x ptr # 十六进制显示指针 ptr
display counter # 每次停下来自动显示 counter 的值
b. 查看局部/全局符号表
info locals # 列出当前栈帧的局部变量及其值
info globals # 列出全局符号表
backtrace # 简要显示所有栈帧
bt full # 完整信息。包括每帧的局部变量值
frame 2 # 切换到第 2 帧进行深入检查
d. 检查寄存器状态
info registers # 打印所有通用寄存器及其当前内容
info registers eax # 查看特定寄存器 eax 的值
九、动态修改变量——现场修复错误
# 将全局计数器重置为 0,免得每次重启都要改源码再编译。set variable counter = 0
# 改变指针指向,以验证内存越界是否导致崩溃。set $rax = 0x601050
十、性能分析与慢速排查
info registers # 打印所有通用寄存器及其当前内容
info registers eax # 查看特定寄存器 eax 的值
# 将全局计数器重置为 0,免得每次重启都要改源码再编译。set variable counter = 0
# 改变指针指向,以验证内存越界是否导致崩溃。set $rax = 0x601050
If your program feels sluggish。you can use GDB’s built‑in TUI mode + perf integration.
| 工具/命令 | 用途及示例 |
|---|---|
| `record` | P记录程序执行过程,可回放查看每一步耗时。至于示例,record start continue record stop record replay |
| `info line *addr` | `addr` 为机器码地址。可定位热点代码所在源文件行号。示例这方面,info line *0x4005f6 |
| `thread apply all bt` | D在多线程环境下一次性打印全部线程栈。帮助定位竞争条件,从示例来看,thread apply all bt |
| `monitor reset` | K使用硬件仿真网站时可快速复位目标板。说到示例,monitor reset |
| `set pagination off` | S关闭分页。让大量输出一次性展示,更适合脚本化分析。说到示例,set pagination off |
|
|---|

