MIPS64平台Valgrind检测基础动态分配时出现无效内存访问
问题背景
在MIPS64架构环境中,使用Valgrind(测试过3.13、3.15、3.22版本)检测一段循环执行基础动态内存分配的程序时,Valgrind报告无效内存访问错误,进程因SIGBUS(信号10)终止。
Valgrind输出信息
-bash-4.3# bin/valgrind ./a.out Memcheck, a memory error detector Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info Command: ./a.out Invalid read of size 8 at 0x40B6EE4: __ctype_init (in /lib64/libc.so.6) by 0x40A7C8C: _init (in /lib64/libc.so.6) by 0x40129D8: call_init (in /lib64/ld-2.16.so) by 0x4012BC8: _dl_init (in /lib64/ld-2.16.so) by 0x400328C: _dl_start_user (in /lib64/ld-2.16.so) Address 0xffffffffffff9000 is not stack'd, malloc'd or (recently) free'd Process terminating with default action of signal 10 (SIGBUS) at 0x40B6EE4: __ctype_init (in /lib64/libc.so.6) by 0x40A7C8C: _init (in /lib64/libc.so.6) by 0x40129D8: call_init (in /lib64/ld-2.16.so) by 0x4012BC8: _dl_init (in /lib64/ld-2.16.so) by 0x400328C: _dl_start_user (in /lib64/ld-2.16.so) Invalid read of size 4 at 0x4019508: __dl_runtime_resolve (in /lib64/ld-2.16.so) by 0x40192D8: __dl_runtime_resolve (in /lib64/ld-2.16.so) Address 0xffffffffffff8900 is not stack'd, malloc'd or (recently) free'd Process terminating with default action of signal 10 (SIGBUS) at 0x4019508: __dl_runtime_resolve (in /lib64/ld-2.16.so) by 0x40192D8: __dl_runtime_resolve (in /lib64/ld-2.16.so) HEAP SUMMARY: in use at exit: 0 bytes in 0 blocks total heap usage: 0 allocs, 0 frees, 0 bytes allocated All heap blocks were freed -- no leaks are possible For counts of detected and suppressed errors, rerun with: -v ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) Bus error
测试程序代码
while(1) { int *ptr = (int *)malloc(sizeof(int)); *ptr = 1; printf("#### Ptr %d\n", *ptr); free(ptr); sleep(1); }
更换多个Valgrind版本后问题仍存在,需排查并解决该问题。
排查与解决步骤
1. 定位问题本质:架构与库的兼容性冲突
从报错栈看,问题发生在glibc动态链接初始化阶段(__ctype_init、__dl_runtime_resolve),而非测试程序本身的内存操作。MIPS64的地址空间布局、ABI规范与x86差异极大,旧版glibc(如这里的2.16)与Valgrind的LibVEX引擎存在兼容性bug,尤其在处理高地址空间(如0xffffffffffff9000这类接近栈顶的地址)时容易触发SIGBUS。
2. 调整Valgrind运行参数绕过冲突
使用以下参数关闭子进程追踪和VEX优化,减少初始化阶段的检测冲突:
bin/valgrind --trace-children=no --vex-iropt-level=0 ./a.out
3. 升级或替换glibc版本
当前使用的glibc 2.16版本过旧,对MIPS64的Valgrind支持不足。尝试升级到glibc 2.23及以上版本,或使用嵌入式Linux发行版提供的MIPS64适配分支。若环境受限无法升级,可尝试静态编译程序:
gcc -static your_program.c -o a.out
静态编译会将glibc直接链接到程序内部,避免动态链接阶段的兼容性问题。
4. 确认Valgrind的架构编译正确性
确保Valgrind是针对当前MIPS64架构(大端/小端)正确编译的,编译时需指定对应架构参数,例如:
./configure --host=mips64-linux-gnu make && make install
如果使用预编译包,需确认包的架构与系统完全匹配,避免交叉编译导致的ABI不兼容。
5. 添加Valgrind抑制规则忽略初始化错误
若上述方法无效,可创建抑制规则跳过这些初始化阶段的错误:
- 生成详细错误日志:
bin/valgrind -v ./a.out > valgrind_errors.log 2>&1
- 创建抑制文件
suppressions.supp:
{ __ctype_init_sigbus Memcheck:Addr8 fun:__ctype_init } { __dl_runtime_resolve_sigbus Memcheck:Addr4 fun:__dl_runtime_resolve }
- 加载抑制文件运行Valgrind:
bin/valgrind --suppressions=suppressions.supp ./a.out
6. 验证程序本身的正确性
先直接运行./a.out,确认程序单独运行不会触发SIGBUS。若程序正常,说明问题完全是Valgrind与系统库的兼容性冲突,无需修改程序代码。
内容的提问来源于stack exchange,提问作者Anshul Kant Saxena

