Linux系统编程Day9 -- gdb (linux)和lldb(macOS)调试工具
往期内容回顾
Git 教程(初阶)
基于Linux系统知识的第一个程序
自动化构建工具-make/Makefile
gcc/g++编译及链接
Vim工具的使用
Linux常用工具(yum与vim)
一、 Linux 下的调试工具 GDB
一、为什么要学习 GDB?
-
调试是开发不可或缺的环节,无论是初学编程还是开发大型项目,都难免会遇到程序崩溃、逻辑错误、死循环等问题。
-
GDB(GNU Debugger)是 Linux/Unix 下最常用的命令行调试工具,能帮助你精确定位问题所在。
-
学会用 GDB,能极大提升排错效率,节省大量调试时间。
-
对于理解程序运行机制、学习底层细节也很有帮助。
二、什么是 GDB?
-
GDB 是 GNU 项目下的调试器,用于调试用 C、C++、Fortran 等语言编写的程序。
-
它允许你:
-
运行程序并监控执行过程
-
设置断点暂停程序
-
查看变量和内存内容
-
单步执行代码
-
跟踪调用栈
-
修改变量值
-
-
GDB 是基于命令行的,但也有很多图形前端(如 DDD、Nemiver、Eclipse 等)用来提升交互体验
三、GDB 的基本使用
1. 编译带调试信息的程序
为了让 GDB 能查看源码信息,必须在编译时加上 -g 参数:
gcc -g hello.c -o hello
原因:gcc/g++默认在编译文件的时候,文件的版本为release版本,无法进行调试,在编译时必须要 加上 -g允许gdb查看源码才能进入调试模式。
gdb ./hello
2. 常用命令示例
命令 | 说明 |
---|---|
run / r | 启动程序 |
break main / b main | 在 main 函数设置断点 |
break 文件名:行号 | 在指定行设置断点 |
next / n | 单步执行下一行(不进入函数内部) |
step / s | 单步执行,进入函数内部 |
continue / c | 继续运行直到下一个断点或程序结束 |
print 变量名 / p | 打印变量值 |
info locals | 查看当前函数所有局部变量 |
backtrace / bt | 查看调用栈 |
list / l | 查看源码(当前行附近) |
quit / q | 退出 GDB |
3、调试流程示例
(gdb) break main # 设置断点
(gdb) break delete num # 删除第num个断点
(gdb) run # 运行程序
(gdb) next # 执行下一行
(gdb) print x # 打印变量 x
(gdb) continue # 继续执行
(gdb) backtrace # 查看调用栈
(gdb) quit # 退出(gdb) p &x #查看变量的地址
(gdb) display x #变量的常显示
(gdb)until num #跳出循环至下一次有效代码行num
(gdb) set var sum = 10 # 修改变量值
(gdb)info locals #查看局部变量
四、总结
优点 | 适用场景 |
---|---|
免费、开源、功能强大 | C/C++ 程序调试 |
支持断点、单步执行、变量查看 | 定位程序崩溃和逻辑错误 |
支持多线程、远程调试 | 复杂项目调试 |
有丰富的命令集和脚本支持 | 自动化调试流程 |
二、macos下的调试工具LLDB
一、macOS 的 LLDB 简介
1. 什么是 LLDB?
-
LLDB 是 Apple 推出的调试器,属于 LLVM 项目的一部分。
-
它是 macOS 和 iOS 平台上的默认调试器,随 Xcode 工具链安装。
-
LLDB 设计现代化,支持最新的编译器生成的调试信息(特别是 Clang/LLVM 生成的 DWARF)。
-
原生支持 ARM64 (Apple Silicon) 架构,支持多线程、异步编程调试。
2. LLDB 与 GDB 的关系
-
LLDB 最初是为了替代 GDB 在苹果生态的地位而开发的。
-
LLDB 和 GDB 在命令行风格上有很多相似之处,但内部架构不同。
-
LLDB 使用现代 C++ 编写,集成 LLVM,调试效率和对新架构的支持更好。
-
GDB 作为 GNU 项目,历史悠久,跨平台广泛,但 macOS 上对最新 Apple 硬件和编译器支持不如 LLDB。
二、macOS LLDB 的安装和启动
-
默认已经安装:macOS 自带 Xcode 或者 Xcode 命令行工具后,会自动安装 LLDB。
-
启动 LLDB:
lldb <program>
进入交互命令行界面,等待用户输入命令
三、LLDB 常用命令详解
任务 | LLDB 命令示例 | 说明 | GDB 对应命令 |
---|---|---|---|
启动程序 | run | 运行程序 | run / r |
设置函数断点 | breakpoint set -n main 或 b main | 在函数名 main 处设置断点 | break main |
设置行断点 | breakpoint set -f file.c -l 42 或 b file.c:42 | 在文件 file.c 的第 42 行设置断点 | break file.c:42 |
列出断点 | breakpoint list 或 br list | 列出所有断点 | info break |
删除断点 | breakpoint delete 1 | 删除断点编号 1 | delete 1 |
单步执行(不进入函数) | next 或 n | 单步执行,不进入函数 | next / n |
单步执行(进入函数) | step 或 s | 单步执行,进入函数 | step / s |
继续执行 | continue 或 c | 继续执行直到下一个断点或程序结束 | continue / c |
打印变量 | print var 或 p var | 打印变量值 | print var / p var |
查看调用栈 | bt 或 thread backtrace | 查看当前调用栈 | backtrace / bt |
查看源码 | list 或 l | 查看当前代码 | list / l |
退出调试 | quit 或 q | 退出调试器 | quit / q |
四、LLDB 的高级功能介绍
1. 对多线程的支持
-
LLDB 支持查看线程列表,切换线程,查看线程状态:
thread list thread select 2 thread info
-
GDB 也支持多线程,但 LLDB 对 macOS 和 ARM64 的线程调试更友好。
2. Watchpoint(监视点)
-
LLDB 支持对变量内存变化设置监视点:
watchpoint set variable myVar
-
适合调试内存相关错误。
3. 表达式求值和脚本
-
LLDB 支持用 Python 脚本扩展功能。
-
可以在调试时写 Python 脚本执行复杂操作。
4. 代码补全与命令历史
LLDB 支持 tab 补全和命令历史,比 GDB 交互体验更好。
五、macOS LLDB 与 GDB 对比总结
特性/维度 | LLDB (macOS) | GDB (macOS) |
---|---|---|
默认安装 | macOS 自带,Xcode 自带 | 需要自己安装 |
支持架构 | 原生支持 ARM64 和 x86_64 | 主要支持 x86_64,ARM64 支持有限 |
调试符号支持 | 完美支持 Apple clang 生成的 DWARF 格式 | 对 Apple DWARF 支持不完全,常报错 |
交互体验 | 命令补全、脚本扩展、历史记录完善 | 较传统,交互性不如 LLDB |
多线程调试 | 优秀 | 支持,但不如 LLDB 友好 |
脚本支持 | 支持 Python | 有脚本支持,但相对较弱 |
适用场景 | macOS 和 iOS 开发首选调试器 | Linux 和跨平台项目常用 |
易用性 | 现代化,用户体验更好 | 历史久远,但命令更繁琐 |
六、简单 LLDB 调试流程示例
gcc -g -O0 gdb.c -o myprog # 编译带调试符号程序
lldb myprog # 启动 lldb 调试器(lldb) b main # 在 main 函数设置断点
(lldb) run # 运行程序
(lldb) n # 单步,不进入函数
(lldb) s # 单步,进入函数
(lldb) p var # 打印变量
(lldb) bt # 查看调用栈
(lldb) c # 继续运行至下一个断点b
(lldb) q # 退出(lldb) display x #变量的常显示
(lldb)until num #跳出循环至下一次有效代码行num
(lldb) expr sum = 10 # 修改变量值
(lldb) frame variable #查看当前函数的所有局部变量
七、总结
-
在 macOS 上调试,强烈推荐用 LLDB。
-
LLDB 对 macOS 和 Apple Silicon 有天然支持,调试体验比 GDB 好很多。
-
GDB 虽然经典且跨平台,但在 macOS 上使用常碰到架构兼容性和调试信息格式问题。
-
如果你熟悉 GDB 命令,LLDB 也能快速上手,命令基本兼容,还支持更多现代功能。