Ubuntu Linux下malloc hooks移除后如何统计malloc调用次数
大型C++项目malloc调用次数统计方案
按操作成本从低到高列两个可直接落地的方案,不需要复杂配置:
方案1:零代码修改,用Valgrind Callgrind实现(适合短时间运行的场景)
你之前选错了Valgrind的工具,Massif本身只做堆内存占用剖析,不统计调用次数,用Callgrind可以直接拿到计数,不需要改项目代码、不需要重新编译:
- 执行以下命令启动你的程序:
valgrind --tool=callgrind --toggle-collect=malloc ./your_program [your_program_args] - 程序运行结束后,当前目录会生成
callgrind.out.<pid>格式的结果文件,执行以下命令即可直接看到malloc总调用次数:callgrind_annotate callgrind.out.<pid> | grep "malloc"
注意:该方案会让程序运行速度下降10~30倍,如果你的项目全量流程运行时间很长,选第二个方案。
方案2:LD_PRELOAD预加载计数库(性能损耗极低,适合大型项目全量运行)
这个方案实现非常简单,不需要改原有项目的代码,性能损耗在5%以内:
- 新建一个名为
malloc_count.c的文件,写入以下代码:#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> static unsigned long long malloc_cnt = 0; static void* (*real_malloc)(size_t) = NULL; void *malloc(size_t size) { if (!real_malloc) { real_malloc = dlsym(RTLD_NEXT, "malloc"); } malloc_cnt++; return real_malloc(size); } __attribute__((destructor)) static void print_result() { fprintf(stderr, "\nTotal malloc calls: %llu\n", malloc_cnt); } - 编译成动态库:
gcc -shared -fPIC -o libmcount.so malloc_count.c -ldl - 启动你的程序时前置环境变量加载这个库即可,程序正常退出时会自动在错误流打印总调用次数:
LD_PRELOAD=./libmcount.so ./your_program [your_program_args]
说明:glibc环境下C++的new默认底层调用malloc,这个计数会包含new触发的malloc请求,如果需要区分可以自行在库里加栈判断逻辑。
此前尝试方案的问题说明
__malloc_hook机制从glibc 2.34版本开始已被正式移除,新发行版系统上无法兼容,不需要再尝试该方案。- Valgrind Massif的设计目标是统计堆内存峰值、分配栈占比,本身不提供调用次数统计能力,没有相关配置项可以开启该功能。
内容的提问来源于stack exchange,提问作者Andreas Pasternak
相关产品推荐
相关产品推荐

