asan简单介绍

42 篇文章 1 订阅
asan是用于检测内存错误的工具,包括use-after-free、heapbufferoverflow、stackbufferoverflow、memoryleaks和doublefree等。在GCC中,可以通过添加编译标志-fsanitize=address来启用asan。对于Android,可以在CMakeLists.txt或build.gradle中配置asan选项,并确保包含对应的asan库。此外,valgrind也是一个类似的工具,可用于检查内存泄漏和错误使用。
摘要由CSDN通过智能技术生成

asan主要用于下面内存错误访问情况

Use after free (dangling pointer dereference)
堆上分配的空间被 free 之后再次使用

Heap buffer overflow
访问的区域在堆上, 并且超过了分配的空间

Stack buffer overflow

访问的区域在栈上, 并且超过了分配给它的空间

Memory leaks
程序结束时未释放堆上分配的内存

Double free 指针重复释放

在makefile里添加-fsanitize=address -g

如: CFLAGS += -fsanitize=address -g -fno-omit-frame-pointer -g -O0

简单的用gcc命令就行 gcc main.c  -fsanitize=address -g -fno-omit-frame-pointer -g -O0 -lm -o test

CMakeLists.txt里添加

set (CMAKE_C_FLAGS_DEBUG "$CMAKE_C_FLAGS_DEBUG}  -fsanitize=address -g -fno-omit-frame-pointer")

set (CMAKE_SHARED_LINKER_FLAG_DEBUG "$CMAKE_SHARED_LINKER_FLAG_DEBUG}   -fsanitize=address -g -fno-omit-frame-pointer")

set (CMAKE_EXE_LINKER_FLAGS "$CMAKE_EXE_LINKER_FLAGS}  -fsanitize=address -g -fno-omit-frame-pointer")

例子1

void main() {

  char *a = "abcde";

  char *bb = calloc(1, 5);

  return;

}

编译后运行,

会提示

==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 5 bytes in 1 object allocated from

#address  in main  .../main.c  3

例子2

void main() {

  char *a = "abcde";

  char *bb = calloc(1, 5);

  strcpy(bb, aa);

  return;

}

则会多提示一个AddressSanitizer, heap-buffer-overflow on address...

#address in main ..... main.c  4

例子3

#include <stdio.h>

void main() {

  int a[10];

  a[15]=15;

   printf("a[15]=%d\n",a[15)];

  return;

}

则会提示AddressSanitizer: stack-buffer-overflow on address.....

#addres in main .... main.c  4

例子4

#include <string.h>

void main() {

  char *aa = calloc(1, 10);

  free(aa);

  strcpy(aa, "abc");

}

则会提示AddressSanitizer: heap-use-after-free on address ....

#address in main.c   5 (strcpy)

freed by thread 

#address in main.c  4 (free)

previously allocated by thread here

#address in main (calloc)

例子5

#include <string.h>

void main() {

  char *aa = calloc(1, 10);

  free(aa);

  free(aa);

}

则会提示AddressSanitizer: attempting double-free on ....

#address in main 5 (第二个free)

freed by thread here

#address in main 4 (第一个free)

Android的可以参考下面的(我还试过)

Address Sanitizer  |  Android NDK  |  Android Developers

深入浅出Android NDK之ASan检测内存越界_android asan_sztaohongtao的博客-CSDN博客

APP 下面的 build.gradle 添加:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                # Can also use system or none as ANDROID_STL.
                arguments "-DANDROID_ARM_MODE=arm", "-DANDROID_STL=c++_shared"
            }
        }
    }
}

CMakeLists.txt 脚本添加:

target_compile_options(${libname} PUBLIC -fsanitize=address -fno-omit-frame-pointer)
set_target_properties(${libname} PROPERTIES LINK_FLAGS -fsanitize=address)

NDK-BUILD

Application.mk 文件添加:

APP_ABI := armeabi-v7a arm64-v8a (已有的,跟asan无关)

APP_STL := c++_shared # Or system, or none.
APP_CFLAGS := -fsanitize=address -fno-omit-frame-pointer
APP_LDFLAGS := -fsanitize=address

Android.mk 文件添加:

APP_STL := c++_shared # Or system, or none.
APP_CFLAGS := -fsanitize=address -fno-omit-frame-pointer
APP_LDFLAGS := -fsanitize=address

LOCAL_CFLAGS : = ......   -fsanitize=address -fno-omit-frame-pointer

LOCAL_SANITIZE := address

LOCAL_LDFLAGS += -fsanitize=address

拷贝 Asan 库到 jniLibs 目录下

Asan 库位于下面路径下:

android-ndk-rxxx/toolchains/llvm/prebuilt

ndk-build命令需要sdk大于27,且NDK_DEBUG=1

比如

ndk-build NDK_DEBUG=1 NDK_PROJECT_PAH=. APP_BUILD_SCRIPT=./build_Android.mk NDK_APPLICATION_MK=./Application.mk NDK_OUT=./out   NDK_LIBS_OUT=./out/libs APP_PLATFORM=android-27

64 位 libclang_rt.asan-aarch64-android.so , 32 位 libclang_rt.asan-arm-android.so ,分别拷贝两个库到 jniLibs 相应的目录下。

这两个库可以在下面找到

Mac /Users/***/Library/Android/sdk/ndk/****/toochains/llvm/prebuilt/darwin-x86_64/lib64/clang/***/lib/linux/

Linux   /home/***/android-ndk-**/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/****/lib/linux/

经验证, 下面这个不需要

新建 wrap.sh 文件,拷贝下面内容到文件中:

#!/system/bin/sh
HERE="$(cd "$(dirname "$0")" && pwd)"
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
ASAN_LIB=$(ls $HERE/libclang_rt.asan-*-android.so)
if [ -f "$HERE/libc++_shared.so" ]; then
    # Workaround for https://github.com/android-ndk/ndk/issues/988.
    export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
else
    export LD_PRELOAD="$ASAN_LIB"
fi
"$@"

另外还有个类似asan的工具, valgrind

命令 valgrind --tool=memcheck --leak-check=full 可执行文件名

最好是可执行文件执行一段时间后进行deinit(即有主动释放内存的),这样在deinit后valgrind就可以检测出其他尚未释放的内存或者中间有错误使用的内存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值