Address Sanitizer: 内存检测工具

发布时间 2023-07-08 22:14:19作者: liqinglucky

原文地址:https://www.cnblogs.com/liqinglucky/p/Address-Sanitizer.html

一、介绍

官方wiki: Home · google/sanitizers Wiki · GitHub

Address Sanitizer(asan)是一个内存检测工具,从gcc 4.8开始,Address Sanitizer成为了GCC的一部分。只要在编译自己的代码时加上响应的编译参数就可以很方便的加上内存检测的功能。

这套sanitizer工具包含了三大件:

  • Address Sanitizer: 检测指针重复释放问题,堆,栈内存溢出问题。

  • Thread Sanitizer[1]: 线程问题。

  • Memory Sanitizer: 内存未初始化问题。

二、使用方法

开源项目Address-Sanitizer-C-Language中有很多使用示例适合初学者了解Address Sanitizer工具。

编译

将Address Sanitizer集成进自己的代码只需要在编译时添加编译参数就可以。

gcc -fsanitize=address -g double_free.c

编译后生成可执行文件

/Address-Sanitizer-C-Language/double_free#  gcc -fsanitize=address -g double_free.c

/Address-Sanitizer-C-Language/double_free# ls
a.out  double_free.c  fixed_double_free.c

如果是使用CMake集成Address Sanitizer的方式[2]

运行

Address-Sanitizer的Log已经给了很详细的分析,根据提示内容修复。以double_free的用例日志举例

/Address-Sanitizer-C-Language/double_free# ./a.out
=================================================================
// 提示内容1:double-free的位置
==716900==ERROR: AddressSanitizer: attempting double-free on 0x602000000010 in thread T0:
    #0 0x7f5acea3740f in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:122
    #1 0x563a2d33e242 in main /root/Address-Sanitizer-C-Language/double_free/double_free.c:15
    #2 0x7f5ace75c0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x240b2)
    #3 0x563a2d33e10d in _start (/root/Address-Sanitizer-C-Language/double_free/a.out+0x110d)

// 提示内容2:第一次free的位置
0x602000000010 is located 0 bytes inside of 8-byte region [0x602000000010,0x602000000018)
freed by thread T0 here:
    #0 0x7f5acea3740f in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:122
    #1 0x563a2d33e236 in main /root/Address-Sanitizer-C-Language/double_free/double_free.c:14
    #2 0x7f5ace75c0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x240b2)

// 提示内容3:内存分配的位置
previously allocated by thread T0 here:
    #0 0x7f5acea37808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x563a2d33e1e5 in main /root/Address-Sanitizer-C-Language/double_free/double_free.c:12
    #2 0x7f5ace75c0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x240b2)

SUMMARY: AddressSanitizer: double-free ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:122 in __interceptor_free
==716900==ABORTING

工作原理

参考[3]Address Sanitizer 用法 - 简书 (jianshu.com)

AddressSanitizer的运行时库替换malloc()/free()。分配缓存前后的空间标记为poisoned,已经被释放的缓存也被标记为poisoned。访问之前检查访问地址是否poisoned,如果是,报告错误。

遇到问题

/usr/bin/ld: source/license2_test.o: in function `_sub_D_00099_0':
/source/license2_test.c:24: undefined reference to `__asan_unregister_globals'
/usr/bin/ld: source/license2_test.o: in function `_sub_I_00099_1':
/source/license2_test.c:24: undefined reference to `__asan_init'
/usr/bin/ld: /source/license2_test.c:24: undefined reference to `__asan_version_mismatch_check_v8'
/source/license2_test.c:24: undefined reference to `__asan_register_globals'
collect2: error: ld returned 1 exit status

网上解决办法:linux - undefined reference to '_asan_init_v4' when compiling - Stack Overflow

参考

NOTE:一些工具,如代码覆盖率和静态分析工具,可以进行类似地设置。然而,其中一些工具的使用更加复杂,因为需要专门的构建和工具链。Sanitizers就是这样一个例子。有关更多信息,请参见https://github.com/arsenm/sanitizers-cmake 。另外,请参阅第14章,其中讨论了AddressSanitizer和ThreadSanitizer。


  1. 线程检查工具 ThreadSanitizer - 简书 (jianshu.com) ↩︎

  2. 14.3 使用AddressSanifier向CDash报告内存缺陷-CMake菜谱(CMake Cookbook中文版)-面试哥 (mianshigee.com) ↩︎

  3. AddressSanitizer&ThreadSanitizer原理与应用 - 知乎 (zhihu.com) ↩︎