一、为什么调试能力很重要
Linux 应用开发真正的难点不只是写代码,而是程序出问题时能不能定位。程序可能在你的机器上正常,在服务器上崩溃;可能测试环境正常,生产环境慢;也可能偶发死锁、内存泄漏、文件句柄耗尽。
调试和排错要形成固定流程:
1 | 确认现象 -> 收集信息 -> 缩小范围 -> 验证假设 -> 修复 -> 回归 |
二、编译时保留调试信息
开发阶段建议使用:
1 | gcc main.c -o app -Wall -Wextra -g -O0 |
说明:
-g:生成调试信息。-O0:关闭优化,调试时变量和代码更接近源码。-Wall -Wextra:打开常用警告。
发布版本可以使用:
1 | gcc main.c -o app -O2 |
如果线上需要分析 core dump,最好保留对应版本的带符号二进制或独立调试符号。
三、GDB 基础
启动:
1 | gdb ./app |
常用命令:
1 | break main |
调试带参数程序:
1 | gdb --args ./app --config app.conf --port 8080 |
进入 GDB 后:
1 | run |
四、Core Dump
开启 core:
1 | ulimit -c unlimited |
运行程序崩溃后,如果生成 core 文件:
1 | gdb ./app core |
查看调用栈:
1 | backtrace |
查看当前帧变量:
1 | info locals |
core dump 是定位崩溃问题最直接的证据。不要只看日志里的 Segmentation fault,要尽量拿到 core 文件。
五、strace
strace 用来观察系统调用。
查看全部系统调用:
1 | strace ./app |
跟踪文件相关调用:
1 | strace -e openat,read,write,close ./app |
跟踪网络:
1 | strace -e trace=network ./app |
统计耗时:
1 | strace -c ./app |
常见用途:
- 程序找不到配置文件。
- 动态库加载失败。
- 网络连接失败。
- 权限不足。
- 程序卡在某个系统调用。
六、lsof 和文件句柄
查看进程打开了哪些文件:
1 | lsof -p <pid> |
查看端口占用:
1 | lsof -i :8080 |
如果程序运行一段时间后报:
1 | Too many open files |
说明文件描述符可能泄漏,或者系统限制太低。
查看限制:
1 | ulimit -n |
七、top、htop 和 ps
查看整体资源:
1 | top |
更友好的交互工具:
1 | htop |
查看某个进程:
1 | ps aux | grep app |
按 CPU 排序:
1 | ps aux --sort=-%cpu | head |
按内存排序:
1 | ps aux --sort=-%mem | head |
八、perf 性能分析
安装:
1 | sudo apt install -y linux-tools-common linux-tools-generic |
采样:
1 | sudo perf record -g ./app |
查看报告:
1 | sudo perf report |
如果程序已经在运行:
1 | sudo perf top -p <pid> |
perf 适合分析 CPU 热点。不要凭感觉优化,先找到真正耗时的位置。
九、内存问题
常见内存问题:
- 内存泄漏。
- 越界访问。
- use-after-free。
- double free。
- 栈溢出。
可以使用 AddressSanitizer:
1 | gcc main.c -o app -g -fsanitize=address -fno-omit-frame-pointer |
也可以使用 Valgrind:
1 | valgrind --leak-check=full ./app |
AddressSanitizer 速度更快,适合开发阶段;Valgrind 不需要重新编译,但运行慢。
十、日志设计
好日志应该包含:
- 时间。
- 级别。
- 模块。
- 关键参数。
- 错误码。
- 请求 id 或任务 id。
示例:
1 | 2026-06-21 11:00:00 INFO server listen port=8080 |
不好的日志:
1 | error |
这类日志没有上下文,出了问题仍然要重新复现。
十一、线上排错流程
推荐顺序:
- 看服务状态:
systemctl status app - 看日志:
journalctl -u app -n 200 - 看进程:
ps aux | grep app - 看端口:
ss -lntp - 看资源:
top - 看文件句柄:
lsof -p <pid> - 看系统调用:
strace -p <pid> - 看性能热点:
perf top -p <pid> - 必要时抓包:
tcpdump
十二、总结
Linux 调试不是背命令,而是建立排错路径。先确认程序是否运行,再看日志和资源,再深入到系统调用、core dump、性能采样。
能写代码只是开发的一半,能在复杂环境里把问题定位出来,才是 Linux 应用开发的关键能力。
- 本文链接: https://blog.hansong.icu/2026/06/21/Linux_Dev_Debug_Performance/
- 版权声明: 本博客所有文章除特别声明外,均默认采用 CC BY-NC-SA 4.0 许可协议。