内存调试技术:断点调试、内存断点、条件断点、watch point、core dump 分析
内存问题,是 C++ 开发者的老朋友了。段错误、内存泄漏、野指针…… 每个都够你喝一壶的。我做了十几年 C++,可以说一半的加班时间都花在了跟内存 bug 斗智斗勇上。
调试内存问题,光靠 printf 大法肯定不行。你需要一套趁手的兵器。今天我就把压箱底的内存调试技术拿出来,跟你好好聊聊。
断点调试:最基础的武器
断点(Breakpoint)是调试器的基本功。说白了,就是让程序在指定行停下来,让你看看现场。
我个人习惯在 GDB 里这么用:
(gdb) break main.cpp:42
(gdb) b MyClass::MyMethod
(gdb) b 88 if ptr == nullptr
嗯,这里要注意:断点打在函数入口时,参数还没初始化。如果你想看参数值,得用 break 加 commands 组合拳。
内存断点:抓野指针的利器
内存断点(Memory Breakpoint / Watchpoint)是专门对付内存问题的。它监视的是内存地址,不是代码行。
我在项目中遇到过最典型的一个场景:某个对象被意外释放了,但还有人在用它。用普通断点根本抓不到,因为崩溃的地方离 bug 源头十万八千里。
这时候就该内存断点出场了:
(gdb) watch *0x7fffffffe000
(gdb) rwatch *0x7fffffffe000
(gdb) awatch *0x7fffffffe000
watch:监视写入操作rwatch:监视读取操作awatch:读写都监视
条件断点:精准打击
条件断点就是带条件的断点。程序只有在条件满足时才会停下来。
我曾经调试过一个内存池,它在第 10000 次分配时出问题。要是没条件断点,我得手动按 F5 一万次…… 想想都可怕。
(gdb) break allocate if count == 10000
(gdb) condition 1 ptr == 0xdeadbeef
条件断点还能跟内存断点结合:
(gdb) watch my_array[1024] if index > 1000
这样只有当 index 超过 1000 时,才监视 my_array[1024] 的变化。效率高多了。
Watch Point:盯住变量的变化
Watch Point 是内存断点的变种。它监视的是变量,不是地址。调试器会自动帮你处理地址变化。
在 Visual Studio 里,你可以右键变量 -> "添加监视"。在 GDB 里:
(gdb) watch my_var
Hardware watchpoint 1: my_var
你想想看,当你在调试一个复杂的链表操作时,某个节点的 next 指针莫名其妙变了。用 Watch Point 盯着它,谁改的立马现形。
| 类型 | 监视对象 | 适用场景 |
|---|---|---|
| 普通断点 | 代码行 | 控制流程 |
| 内存断点 | 内存地址 | 内存越界、野指针 |
| 条件断点 | 代码行 + 条件 | 循环、高频调用 |
| Watch Point | 变量 | 变量值意外变化 |
Core Dump 分析:事后诸葛亮
Core Dump 是程序崩溃时留下的"尸体"。它包含了程序崩溃那一刻的内存快照、寄存器状态、调用栈等信息。
我建议所有线上服务都开启 Core Dump:
# 设置 core 文件大小不限
ulimit -c unlimited
# 设置 core 文件命名格式
echo "/tmp/core.%e.%p" > /proc/sys/kernel/core_pattern
分析 Core Dump 的经典流程:
- 用 GDB 加载 core 文件:
gdb ./my_program core.12345 - 看崩溃位置:
bt(backtrace) - 看局部变量:
info locals - 看寄存器:
info registers - 看内存:
x/10gx $rsp
知识体系总览
下面这张图,把今天讲的内存调试技术串起来了:
实战经验总结
调试内存问题,我总结了一套心法:
- 先复现,再定位:不能稳定复现的 bug,先别急着上调试器。加日志、加断言,把现场固定下来。
- 从外到内:先看 Core Dump,再看调用栈,最后才上断点。别一上来就单步执行。
- 怀疑一切:内存问题往往不是你以为的地方。我曾经花了一整天查一个空指针,最后发现是另一个线程把内存给释放了。
- 善用工具:Valgrind、AddressSanitizer、GDB 的 TUI 模式…… 这些工具能帮你省下大量时间。
调试内存问题,说白了就是跟计算机玩侦探游戏。你掌握的工具越多,破案的速度就越快。今天讲的这些技术,每一个我都实打实地在项目里用过。希望它们也能帮你少加几天班。
公众号:蓝海资料掘金营,微信deep3321