内存泄漏工具asan

简介

https://zhuanlan.zhihu.com/p/360135083

使用方式

添加编译选项

 -Lasan -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer

编写代码文件,如添加test_asan.c

#include<stdio.h>
#include<stdlib.h>

int main(){
//未释放的内存,会产生内存泄漏
    int* arr = (int*)malloc(sizeof(int) * 10);
    return 0;
}

1.gcc添加方式

gcc -g test_asan.c -o t1 -Lasan -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer

2.CMakeLists添加方式

cmake_minimum_required(VERSION 2.8)

project(test C)
set(CMAKE_C_STANDARD 99)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Lasan -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer")

add_executable(t1 test_asan.c)

ps:一般需要添加-g,否则仅仅会输出错误,找不到对应函数与行号。
重新编译生成可执行文件
查找动态库位置

find /usr -name 'libasan.so'
#/usr里面没有也可以全局查找或自行安装
find / -name 'libasan.so'
#输出位置如下
/usr/local/lib64/libasan.so

添加动态库

export LD_PRELOAD=/usr/local/lib64/libasan.so

执行程序,可以看到内存泄漏问题并定位

./t1
=================================================================
==2154==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 40 byte(s) in 1 object(s) allocated from:
    #0 0xffff852eb67b in __interceptor_malloc ../../.././libsanitizer/asan/asan_malloc_linux.cc:62
    #1 0x400853 in main /home/lichangshi/ML2/my_test/test_ascan.c:5
    #2 0xffff850a1723 in __libc_start_main (/lib64/libc.so.6+0x21723)
    #3 0x40076b  (/home/lichangshi/ML2/my_test/t1+0x40076b)
    #4 0xffffe963f53c  (<unknown module>)

第二次编译之前需要清除添加的动态库

unset LD_PRELOAD

注意:
一定要在编译之后添加动态库位置,如果在编译前添加libasan.so动态库,编译阶段输出以下错误,CMake无法生成可执行文件。

    =================================================================
    ==2644==ERROR: LeakSanitizer: detected memory leaks

    Direct leak of 112 byte(s) in 1 object(s) allocated from:
        #0 0xffffa2f3b82b in __interceptor_calloc ../../.././libsanitizer/asan/asan_malloc_linux.cc:70
        #1 0xf2748b in xcalloc ../.././libiberty/xmalloc.c:162
        #2 0xf2463b in htab_create_typed_alloc ../.././libiberty/hashtab.c:357
        #3 0xef0243 in linemap_init(line_maps*, unsigned int) ../.././libcpp/line-map.c:354
        #4 0x542aa3 in general_init ../.././gcc/toplev.c:1141
        #5 0x542aa3 in toplev::main(int, char**) ../.././gcc/toplev.c:2092
        #6 0x544823 in main ../.././gcc/main.c:39
        #7 0xffffa2ab1723 in __libc_start_main (/lib64/libc.so.6+0x21723)
        #8 0x544c8b  (/usr/local/libexec/gcc/aarch64-unknown-linux-gnu/7.3.0/cc1+0x544c8b)
        #9 0xfffff243f2e6  (<unknown module>)
...省略

上述错误显示的文件为linux中的代码文件,推测是cmake可能存在内存泄漏问题,或cmake的执行代码中的malloc被替换为Ascan中的申请方式可能无法正确执行。具体原因还请相关专业人士解答。

常见错误类型

1.内存泄漏(Memory leaks),即申请的内存未释放。

#include<stdio.h>
#include<stdlib.h>

int main(){
//未释放的内存,会产生内存泄漏
    int* arr = (int*)malloc(sizeof(int) * 10);
    return 0;
}
./t1
=================================================================
==2154==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 40 byte(s) in 1 object(s) allocated from:
    #0 0xffff852eb67b in __interceptor_malloc ../../.././libsanitizer/asan/asan_malloc_linux.cc:62
    #1 0x400853 in main /home/lichangshi/ML2/my_test/test_ascan.c:5
    #2 0xffff850a1723 in __libc_start_main (/lib64/libc.so.6+0x21723)
    #3 0x40076b  (/home/lichangshi/ML2/my_test/t1+0x40076b)
    #4 0xffffe963f53c  (<unknown module>)

2.栈溢出(Stack buffer overflow),函数中的变量,参数,引用,指针,返回地址等存储在栈中,若超出栈的容量会导致栈溢出,常见情形为递归过深或申请的数组过大。

void stack_buffer_overflow(){
    long long len = 1024*1024*1024;
    double a[len];
    for(int i = 0; i < len; i++){
        a[i] = -1.0;
    }
    return;
}

int main(){
    stack_buffer_overflow();
    return 0;
}
ASAN:DEADLYSIGNAL
=================================================================
==10239==ERROR: AddressSanitizer: stack-overflow on address 0xfffde74c4500 (pc 0x000000400b0c bp 0xffffe74c4510 sp 0xfffde74c4500 T0)
    #0 0x400b0b in stack_buffer_overflow /home/lichangshi/ML2/my_test/test_asan.c:13
    #1 0x400b4f in main /home/lichangshi/ML2/my_test/test_asan.c:19
    #2 0xffff97301723 in __libc_start_main (/lib64/libc.so.6+0x21723)
    #3 0x40093b  (/home/lichangshi/ML2/my_test/build/test+0x40093b)

SUMMARY: AddressSanitizer: stack-overflow /home/lichangshi/ML2/my_test/test_asan.c:13 in stack_buffer_overflow
==10239==ABORTING

SUMMARY: AddressSanitizer: stack-overflow (/home/lichangshi/ML2/my_test/build/test+0x400b0b) in stack_buffer_overflow
==10284==ABORTING

3.堆溢出(heap buffer overflow)。堆中存储动态申请内存,如malloc(), calloc(), new int[]等,常见情况为访问到申请内存之外的地址。

void heap_buffer_overflow(){
    int* a = (int*)malloc(sizeof(int)*10);
    a[11] = 1;
    return;
}

int main(){
    heap_buffer_overflow();
    return 0;
}
=================================================================
==10349==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xffffb4c00f7c at pc 0x000000400c44 bp 0xfffffbffb640 sp 0xfffffbffb658
WRITE of size 4 at 0xffffb4c00f7c thread T0
    #0 0x400c43 in heap_buffer_overflow /home/lichangshi/ML2/my_test/test_asan.c:20
    #1 0x400c67 in main /home/lichangshi/ML2/my_test/test_asan.c:25
    #2 0xffffb8091723 in __libc_start_main (/lib64/libc.so.6+0x21723)
    #3 0x4009cb  (/home/lichangshi/ML2/my_test/build/test+0x4009cb)

0xffffb4c00f7c is located 4 bytes to the right of 40-byte region [0xffffb4c00f50,0xffffb4c00f78)
allocated by thread T0 here:
    #0 0xffffb838b67b in __interceptor_malloc ../../.././libsanitizer/asan/asan_malloc_linux.cc:62
    #1 0x400be7 in heap_buffer_overflow /home/lichangshi/ML2/my_test/test_asan.c:19
    #2 0x400c67 in main /home/lichangshi/ML2/my_test/test_asan.c:25
    #3 0xffffb8091723 in __libc_start_main (/lib64/libc.so.6+0x21723)
    #4 0x4009cb  (/home/lichangshi/ML2/my_test/build/test+0x4009cb)
    #5 0xfffffbfff53c  (<unknown module>)

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/lichangshi/ML2/my_test/test_asan.c:20 in heap_buffer_overflow
Shadow bytes around the buggy address:
  0x200ff6980190: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200ff69801a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200ff69801b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200ff69801c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200ff69801d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x200ff69801e0: fa fa fa fa fa fa fa fa fa fa 00 00 00 00 00[fa]
  0x200ff69801f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200ff6980200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200ff6980210: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200ff6980220: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200ff6980230: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
==10349==ABORTING

4.全局溢出(Global buffer overflow)。
把超大静态数组/放到全局变量中或越界访问静态数组,不写了。
等等

参考链接

https://zhuanlan.zhihu.com/p/360135083
https://www.jianshu.com/p/9e85345e500b
栈溢出是什么:
https://zhuanlan.zhihu.com/p/73411916
堆溢出是什么:
https://eternalsakura13.com/2018/02/28/heap_exp1/

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值