如何通过perf probe获取malloc分配大小并修复数值错误
问题根源分析
你遇到的问题本质上是两个核心原因:
- 64位系统调用约定的差异:Linux下x86_64架构遵循System V ABI,函数的第一个参数是通过
rdi寄存器传递的,而非32位程序里依赖栈帧偏移的逻辑。你之前用-8(%bp)的写法是32位环境下的老思路,放到64位系统里完全不适用。 - 编译优化导致帧指针被省略:当用
O3编译(甚至部分O0场景下的大型程序),编译器会自动启用-fomit-frame-pointer,此时rbp不再作为固定的帧指针使用,基于%bp的偏移自然无法获取正确的值。
正确的解决方法
方法1:利用perf probe的自动参数解析(推荐)
perf probe可以借助libc的调试信息自动识别函数参数,完全不用手动计算偏移或寄存器位置。
先安装libc的调试包(系统不同命令略有差异):
- CentOS/RHEL:
sudo yum install glibc-devel - Debian/Ubuntu:
sudo apt install libc6-dbg
- CentOS/RHEL:
创建追踪malloc参数的probe事件:
perf probe -x /lib64/libc.so.6 'malloc allocated_size=$arg1'这里的
$arg1就是malloc的第一个参数——也就是你要追踪的内存分配大小。记录事件并同时采集调用栈:
perf record -g -e probe_libc:malloc ./your_program-g参数是用来启用调用栈回溯的,这样就能同时看到每个malloc调用的调用链路。查看最终结果:
perf report你会在每个事件条目里看到准确的
allocated_size数值,以及对应的完整调用栈。
方法2:直接读取寄存器值(无调试包时可用)
如果没法安装调试包,基于x86_64的调用约定,malloc的size参数存在rdi寄存器中,直接读取该寄存器即可:
perf probe -x /lib64/libc.so.6 'malloc allocated_size=%rdi'
后续的记录和查看步骤和方法1完全一致。
验证测试
用你提供的测试小程序:
for (int i=0; i<10; i++) malloc(i);
不管用O0还是O3编译,用上述方法创建probe后,perf report都会显示正确的0-9的size值。对于大型程序,这种基于寄存器或自动参数解析的方式,也不会受编译优化或栈帧布局变化的影响。
内容的提问来源于stack exchange,提问作者Phạm Văn Thông
相关产品推荐
相关产品推荐

