--show-reachable=yes 不开启内存泄漏检测,而是让 valgrind 报告程序退出时仍被指针引用但未释放的“still reachable”内存;这类内存未必是 bug,需结合指针生命周期与程序语义判断是否正常。

什么是 --show-reachable=yes 的输出
--show-reachable=yes 不是开启“检测内存泄漏”,而是控制 Memcheck 是否报告那些「程序退出时仍被指针引用、但未显式释放」的内存块。这类内存叫 still reachable,它不等于 bug —— 很多是全局缓存、单例对象、或 main 函数栈上保存的指针所指向的堆内存。Valgrind 默认不显示它们,因为开发者通常只关心真正丢失控制权的泄漏(definitely lost / possibly lost)。
怎么判断 still reachable 是问题还是正常现象
关键看指针生命周期是否与程序语义一致:
- 如果你在
main()开头 malloc 一块配置缓存,并在整个程序中通过全局指针访问它,那退出时仍是still reachable—— 这是预期行为,不是泄漏 - 如果某个函数内部 malloc 后把地址存进一个 static 指针,但该函数本不该长期持有这块内存(比如是临时解析结果),那它就属于设计疏漏,应改用局部变量或显式 free
- 某些 C++ 库(如 glibc 的
__libc_malloc内部缓存)也会产生少量still reachable,只要总量稳定(比如固定几百字节)、不随输入规模增长,基本可忽略
--show-reachable=yes 常见误读点
很多人看到 still reachable: 128 bytes in 2 blocks 就以为有泄漏,其实容易踩这几个坑:
-
--show-reachable=yes必须和--leak-check=full一起用才生效;单独加它不会改变 leak summary 的分类逻辑 - 它不改变
definitely lost的判定 —— 那些真正没指针指向、无法再访问的内存,无论加不加这个选项都会报 - 输出里出现大量
still reachable且集中在某个第三方库调用栈(比如libstdc++.so中的std::string::_Rep::_S_create),大概率是该库内部管理策略,不是你的代码问题 - 如果关闭优化(
-O0)后still reachable明显变多,可能是编译器优化原本把某些临时指针提前置空了,而调试模式保留了冗余引用
要不要在 CI 或发布前检查 still reachable
一般不用。CI 中建议只关注:definitely lost > 0 或 possibly lost > 0。因为 still reachable 的判定高度依赖编译器行为、链接顺序、甚至 libc 版本 —— 同一份代码在不同机器上可能差几十字节,不具备可比性。真正要盯的是「随请求次数线性增长」的 still reachable,那说明你无意中把短期资源挂到了长生命周期对象上(比如把 per-request buffer 存进了全局 map)。











