简介
谷歌有一系列Sanitizer工具,可用于排查程序中内存相关的问题。常用的Sanitizer工具包括:
- Address Sanitizer(ASan):用于检测内存使用错误。
- Leak Sanitizer(LSan):用于检测内存泄漏。
- Thread Sanitizer(TSan):用于检测多线程间的数据竞争和死锁。
- Memory Sanitizer(MSan):用于检测使用未初始化内存的行为。
本文重点介绍ASan工具的使用。
ASAN工具作用
ASan工具可以检测出程序不可理使用内存的行为,主要包括:
注:ASan内部包含LSan,故ASan也可以用来检测内存泄漏相关问题。
ASAN工具原理
- 在编译时,ASan会替换malloc/free接口;
- 在程序申请内存时,ASan会额外分配一部分内存(影子内存)来标识改内存的状态;
- 在程序使用内存时,ASan会额外进行判断,确认该内存是否可以被访问,并在访问异常时给出错误信息。
ASAN工具安装
ASan已经集成在GCC 4.8中,但GCC 4.9及以上版本才支持 Address Sanitizer 的所有功能。
可知,当前GCC版本已支持ASan,故无须再安装。
ASAN工具使用
GCC编译选项
-fsanitize=address:开启内存越界检测;
-fsanitize-recover=address:一般后台程序为保证稳定性,不能遇到错误就简单退出,而是继续运行,采用该选项支持内存出错之后程序继续运行,需要叠加设置ASAN_OPTIONS=halt_on_error=0才会生效;若未设置此选项,则内存出错即报错退出;
-fno-stack-protector:去使能栈溢出保护;
-fno-omit-frame-pointer:去使能栈溢出保护
ASAN调试示例
测试示例一
测试程序
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 void func(void)
6 {
7 char* str = NULL;
8 memcpy(str, "test", sizeof("test"));
9 }
10
11 int main(void)
12 {
13 printf("hello world!\n");
14
15 func();
16
17 return 0;
18 }
按如下方式编译,并执行测试
lx@lx-virtual-machine:~/asan$ gcc main.c -fsanitize=address -fsanitize-recover=address -fno-stack-protector -fno-omit-frame-pointer
lx@lx-virtual-machine:~/asan$
lx@lx-virtual-machine:~/asan$ ./a.out
hello world!
ASAN:DEADLYSIGNAL
=================================================================
==6880==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000001 (pc 0x7fd7df251255 bp 0x7ffc24aea420 sp 0x7ffc24ae9b88 T0)
==6880==The signal is caused by a WRITE memory access.
==6880==Hint: address points to the zero page.
#0 0x7fd7df251254 (/lib/x86_64-linux-gnu/libc.so.6+0xbb254)
#1 0x7fd7df6006ce (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x796ce)
#2 0x5637740ca9b1 in func (/home/lx/asan/a.out+0x9b1)
#3 0x5637740ca9c9 in main (/home/lx/asan/a.out+0x9c9)
#4 0x7fd7df1b7c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
#5 0x5637740ca8a9 in _start (/home/lx/asan/a.out+0x8a9)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib/x86_64-linux-gnu/libc.so.6+0xbb254)
==6880==ABORTING
可知,测试结果符合分析预期。
参考
https://blog.csdn.net/qq_15437629/article/details/114440930