内存问题检查工具——Address Sanitizer(ASAN)

内存问题检查工具——Address Sanitizer(ASAN)

Address Sanitizer(ASAN)是gcc自带的内存问题检查工具,比较轻量级,非常适合单元测试时检查内存问题。使用也比较简单,只需要在编译时候加“-fsanitize=address -fno-omit-frame-pointer” 即可。若想更精确查看到源码位置,可以加 “-g” 编译debug版本。下面给出几个简单案例。

案例一:内存泄漏

#include
#include

int main() {
    void* buf = malloc(1024);
    return 0;
}

编译:“gcc hello.c -fsanitize=address -fno-omit-frame-pointer -g” ,然后直接执行 ./a.out 即可:

=================================================================
==3440094==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 1024 byte(s) in 1 object(s) allocated from:
    #0 0x7f1530026808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x55c8c0e8119e in main /home/loongknown/test/hello.c:5
    #2 0x7f152fd4b082 in __libc_start_main ../csu/libc-start.c:308

SUMMARY: AddressSanitizer: 1024 byte(s) leaked in 1 allocation(s).

案例二:读越界

#include
#include

int main() {
    int a[10] = {0};
    int x = a[10];
    return 0;
}

编译和执行同上:

=================================================================
==3440706==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffcdc0fdf68 at pc 0x55c54dad2352 bp 0x7ffcdc0fdef0 sp 0x7ffcdc0fdee0
READ of size 4 at 0x7ffcdc0fdf68 thread T0
    #0 0x55c54dad2351 in main /home/loongknown/test/hello.c:6
    #1 0x7f70259e6082 in __libc_start_main ../csu/libc-start.c:308
    #2 0x55c54dad212d in _start (/home/loongknown/test/a.out+0x112d)

Address 0x7ffcdc0fdf68 is located in stack of thread T0 at offset 88 in frame
    #0 0x55c54dad21f8 in main /home/loongknown/test/hello.c:4

  This frame has 1 object(s):
    [48, 88) 'a' (line 5) <== Memory access at offset 88 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/loongknown/test/hello.c:6 in main
Shadow bytes around the buggy address:
  0x10001b817b90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001b817ba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001b817bb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001b817bc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001b817bd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10001b817be0: 00 00 f1 f1 f1 f1 f1 f1 00 00 00 00 00[f3]f3 f3
  0x10001b817bf0: f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001b817c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001b817c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001b817c20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001b817c30: 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
==3440706==ABORTING

越界源码位置和越界的地址都有清晰的显示。

案例三:写越界

#include
#include

int main() {
    int a[10] = {0};
    a[10] = 1;
    return 0;
}

同上编译和执行:

=================================================================
==3441478==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd938896e8 at pc 0x55e6f9bc8352 bp 0x7ffd93889680 sp 0x7ffd93889670
WRITE of size 4 at 0x7ffd938896e8 thread T0
    #0 0x55e6f9bc8351 in main /home/loongknown/test/hello.c:6
    #1 0x7fd974ba6082 in __libc_start_main ../csu/libc-start.c:308
    #2 0x55e6f9bc812d in _start (/home/loongknown/test/a.out+0x112d)

Address 0x7ffd938896e8 is located in stack of thread T0 at offset 88 in frame
    #0 0x55e6f9bc81f8 in main /home/loongknown/test/hello.c:4

  This frame has 1 object(s):
    [48, 88) 'a' (line 5) <== Memory access at offset 88 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/loongknown/test/hello.c:6 in main
Shadow bytes around the buggy address:
  0x100032709280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100032709290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000327092a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000327092b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000327092c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x1000327092d0: 00 00 f1 f1 f1 f1 f1 f1 00 00 00 00 00[f3]f3 f3
  0x1000327092e0: f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000327092f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100032709300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100032709310: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100032709320: 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
==3441478==ABORTING

推荐大家尝试使用!本文结束。

你可能感兴趣的:(开发调试工具,调试工具,内存检查,内存泄露,读写内存越界,ASAN)