memory sanitizer
1. 简介
MemorySanitizer简称msan,用于发现C/C++程序中对未初始化内存的读取。
msan是比特精度的。
msan的功能是Valgrind功能的子集,但运行速度更快。
msan使用stderr打印错误报告
msan发现错误即报告,而不是等到程序即将结束时统一报告
msan发现如下bug并报告warning:
在条件分支中使用未初始化的值。
使用未初始化的指针进行内存访问。
函数返回未初始化的值(这是未定义行为,可以使用
-fno-sanitize-memory-param-retval
来disable这项检查)。传递未初始化数据到一些libc函数中。
2. 使用方法
2.1 常用使用方法
使用clang编译器
使用编译选项
-fsanitize=memory -fPIE -pie -fno-omit-frame-pointer -g
默认错误报告是fatal的,即发现并报告第一个错误后就退出,如需发现多个错误需使用编译选项
-fsanitize-recover=memory
例如如下程序a.cc:
1 | #include <iostream> |
编译:
1 | $ clang++ -fsanitize=memory -fPIE -pie -fno-omit-frame-pointer -g -fsanitize-recover=memory a.cc |
运行:
1 | $ ./a.out |
输出:
1 | ==118555==WARNING: MemorySanitizer: use-of-uninitialized-value |
2.2 简单使用方法
仅使用-fsanitize=memory
和-g
两个编译选项。
1 | $ clang++ -fsanitize=memory -g a.cc && ./a.out |
3. 追踪内存分配位置
msan可以追踪未初始化值的内存分配位置并报告。
启用该追踪需使用编译选项-fsanitize-memory-track-origins
。
该追踪会额外减慢程序速度1.5x~2.5x。
例如对于上面的程序a.cc:
1 | $ clang++ -fsanitize=memory -fPIE -pie -fno-omit-frame-pointer -g -fsanitize-recover=memory -fsanitize-memory-track-origins a.cc |
4. 注意
为了更好地使用msan,程序中的所有代码都需要被msan插桩(使用-fsanitize=memory
编译),包括链接的库(尤其是c++标准库libc++)。
否则未插桩的代码会导致msan报告假阳性。
参考该文档使用msan构建c++标准库。
5. 参考文献
此文章采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Anthony Li's Blogs!