简介
谷歌有一系列Sanitizer工具,可用于排查程序中内存相关的问题。常用的Sanitizer工具包括:
- Address Sanitizer(ASan):用于检测内存使用错误。
- Leak Sanitizer(LSan):用于检测内存泄漏。
- Thread Sanitizer(TSan):用于检测多线程间的数据竞争和死锁。
- Memory Sanitizer(MSan):用于检测使用未初始化内存的行为。
本文重点介绍ASan工具的使用。
注:之前介绍的内存泄漏问题分析工具之【Tcmalloc】的使用参考:https://blog.youkuaiyun.com/liuxu324/article/details/140087281
ASAN工具作用
ASan工具可以检测出程序不合理使用内存的行为,主要包括:
- 堆内存越界
- 栈内存越界
- 全局变量越界
- 函数返回局部变量
- 使用未初始化内存(空指针)
- 使用已释放内存(野指针)
- 重复释放
- 内存泄漏
注:ASan内部包含LSan,故ASan也可以用来检测内存泄漏相关问题。
ASAN工具原理
- 在程序编译时,ASan会替换malloc/free接口;
- 在程序申请内存时,ASan会额外分配一部分内存(影子内存)来标识该内存的状态;
- 在程序使用内存时,ASan会额外进行判断,确认该内存是否可以被访问,并在访问异常时给出错误信息。
使用说明
ASAN工具安装
ASan已经集成在GCC 4.8中,但GCC 4.9及以上版本才支持 Address Sanitizer 的所有功能。
可知,当前GCC版本已支持ASan,故无须更新。
GCC编译选项
-fsanitize=address:开启内存越界检测;
-fsanitize-recover=address:一般后台程序为保证稳定性,不能遇到错误就简单退出,而是继续运行,采用该选项支持内存出错之后程序继续运行,需要叠加设置ASAN_OPTIONS=halt_on_error=0才会生效,若未设置此选项,则内存出错即报错退出;
-fno-stack-protector:使能栈溢出保护;
-fno-omit-frame-pointer:使能栈溢出保护
注:加上-g编译选项。
ASAN调试示例
测试示例一:操作内存越界
测试程序
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 void func(void)
6 {
7 char str[5] = {
0};
8 strncpy(str, "test", strlen("test"));
9 printf("1: %s\n", str);
10 //str[0] = (char)'T';
11 str[5] = (char)'T';
12 printf("2: %s\n", str);
13 }
14
15 int main(