linux下可用mallinfo或malloc_stats快速查看堆使用概况,但二者仅提供当前线程快照且不涵盖mmap分配;需详细指标应换用jemalloc等可观测性强的分配器。

Linux下用mallinfo或malloc_stats快速看堆使用概况
标准C++不提供跨平台堆统计接口,但glibc提供了几个轻量级函数,适合开发期快速诊断。注意它们只反映当前线程调用malloc家族分配器的状态,不包含new直接调用mmap的大块内存(比如某些STL容器的备用策略)。
常用组合:
-
mallinfo()返回struct mallinfo,字段如uordblks(已分配字节数)、fordblks(空闲字节数),但部分字段在较新glibc中已弃用,数值可能不准 -
malloc_stats()直接打印到stderr,输出类似Arena 0: 123456 bytes in 789 chunks,适合日志捕获——用freopen("/tmp/malloc-stats", "w", stderr)临时重定向再读取 - 两者都不支持实时增量或历史趋势,仅快照
用libmalloc或jemalloc替代默认分配器获取详细指标
如果需要每块分配的大小、调用栈、生命周期,必须换用可观测性强的分配器。glibc默认malloc不记录调用栈;jemalloc是更现实的选择。
启用步骤:
- 编译时链接:
g++ -o myapp main.cpp -ljemalloc - 运行时开启统计:
MALLOC_CONF="stats_print:true,lg_prof_sample:17" ./myapp(lg_prof_sample:17表示约128KB采样粒度) - 触发dump:
kill -SIGUSR2 $(pidof myapp)生成je_malloc.prof,用pprof可视化:pprof --svg ./myapp je_malloc.prof > heap.svg - 注意:启用profiling会显著降低性能,仅限调试;生产环境建议用
stats_print:false+ 定期malloc_stats_print()手动触发
Windows上用_heapwalk和_heapchk做基础校验
MSVC CRT提供有限堆检查能力,无法获取分配位置或时间,但能发现损坏和泄漏迹象。
典型用法:
-
_heapchk()返回_HEAPOK或_HEAPBADBEGIN等错误码,建议在关键路径前后调用 -
_heapwalk(&entry)遍历所有块,entry._useflag == _USEDENTRY表示已分配,entry._size给出大小——但不区分用户数据和填充字节,且多线程下需加锁 - 不支持按调用栈聚合,也不能导出为图表;配合Application Verifier工具可补足部分能力
自己hookmalloc/free实现轻量级统计(不推荐用于生产)
若无法替换分配器又需要简单计数,可在main前用__attribute__((constructor))替换符号。但风险极高:
- 必须同时hook
malloc、realloc、free、calloc,漏一个就导致崩溃 - 递归调用风险:统计本身要分配内存,需用预分配缓冲区或
brk()系统调用绕过malloc - 多线程下计数需
std::atomic或pthread_mutex_t保护,但锁本身也占用堆——形成循环依赖 - 示例片段(仅示意):
void* malloc(size_t size) { static void* (*real_malloc)(size_t) = nullptr; if (!real_malloc) real_malloc = (void*(*)(size_t))dlsym(RTLD_NEXT, "malloc"); atomic_fetch_add(&total_allocated, size); return real_malloc(size); }
真正需要图表和长期监控,别手写hook——直接上jemalloc或TCMalloc,它们内置了HTTP接口(如http://localhost:8080/heapz)和Prometheus metrics导出能力。自己拼凑的统计容易漏边角情况,比如std::string的SSO模式根本不走malloc。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











