使用ASAN能够比较方便的定位到内存的相关问题,而且以及集成到gcc中(gcc 6已经支持),更改相应的选项就可以实现。
ASAN可以定位的内存问题有:内存越界(堆内存越界,栈内存越界,全局变量越界),内存释放后使用,读取未初始化内存,内存泄漏。
编译时加上如下编译选项,就可以实现
-fsanitize=address (开启asan功能)
-fsanitize-recover=address (检查到错误之后,继续运行,需要设置环境变量export ASAN_OPTIONS=halt_on_error=0:log_path=err.log, err.log即保存的报错文件,可以自行修改路径和名称)
简单写一个验证,下面这个程序有明显的栈内存越界问题
#include
using namespace std;
int main(){
int array[100];
array[101] = 1;
return array[101];
}
在命令行执行以下命令,完成环境变量的配置和程序的编译
export ASAN_OPTIONS=halt_on_error=0:log_path=err.log
g++ test.cpp -fsanitize=address -fsanitize-recover=address
运行生成的程序,能够得到报错文件日志:
=================================================================
==1945174==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffde0f003f4 at pc 0x55bfe0b0b36d bp 0x7ffde0f00220 sp 0x7ffde0f00210
WRITE of size 4 at 0x7ffde0f003f4 thread T0
#0 0x55bfe0b0b36c in main (/home/station/.../a.out+0x136c)
#1 0x7f8178218082 in __libc_start_main ../csu/libc-start.c:308
#2 0x55bfe0b0b1cd in _start (/home/station/.../a.out+0x11cd)
Address 0x7ffde0f003f4 is located in stack of thread T0 at offset 452 in frame
#0 0x55bfe0b0b298 in main (/home/station/.../a.out+0x1298)
This frame has 1 object(s):
[48, 448) 'array' (line 5) <== Memory access at offset 452 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/home/station/.../a.out+0x136c) in main
Shadow bytes around the buggy address:
0x10003c1d8020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10003c1d8030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10003c1d8040: 00 00 00 00 00 00 f1 f1 f1 f1 f1 f1 00 00 00 00
0x10003c1d8050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10003c1d8060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10003c1d8070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[f3]f3
0x10003c1d8080: f3 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00
0x10003c1d8090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10003c1d80a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10003c1d80b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10003c1d80c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc