AndroidStudio如何使用Address Sanitizer(ASan)检测内存错误

github-samplecode:https://github.com/MitnickG/Android.git
Google原文:https://developer.android.com/ndk/guides/asan#cmake

当使用VisualStudio编译cpp代码时,有一键选择编出ASan版本从而检测内存错误的功能。

但AndroidStudio用到NDK时,从API27开始才支持ASan检测。

在AS中使用ASan需要注意的是,ASan的CPU开销约为2倍,代码大小开销在50%到2倍之间,并且内存开销很大,约为2倍。
官方建议对于64位ARM(一般现在的设备都是这个了),建议使用HWAddress Sanitizer

但本文还是记录下,使用ASan的几个坑。

先写使用流程:

  • 需要准备的文件有:

1、wrap.sh(自己写一个,内容如下):(log_to_syslog=false原文没有介绍,之后可以改成true试试看会有什么不同)

#!/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_L
<think>好的,我现在需要帮助用户了解如何使用AddressSanitizer进行内存错误检测,包括配置和运行的教程。首先,我得回忆一下用户提供的引用内容,看看里面有什么有用的信息。 根据用户给的引用[1],提到使用gcc编译时加上-fsanitize=address选项,还有调试符号-g。引用[2]是关于Android Studio中配置Gradle文件使用ASan,而引用[3]是官方的Wiki页面,可能包含更多示例和详细说明。用户的问题主要是在一般环境下如何使用ASan,可能涉及编译和运行的步骤,也可能需要示例代码。 首先,我应该分步骤讲解如何配置和运行,比如不同的编译器如GCC和Clang,可能还有CMake的情况。需要确保用户知道在编译时必须添加那个选项,并且需要调试符号。然后,示例代码部分,可能写一个简单有内存错误的C程序,比如数组越界或者内存泄漏,然后展示如何编译运行,ASan会如何报告错误。 然后,用户可能需要了解如何解读ASan的输出,比如错误类型、堆栈跟踪等信息。这部分需要简明扼要地解释常见的错误类型,比如堆溢出、栈溢出、使用释放后的内存等。 接下来,注意事项部分,比如不能与其他内存检测工具混用,性能影响,以及如何关闭优化等。这些对用户实际使用中可能会遇到的问题有帮助。 最后,生成相关问题,可能涉及不同环境下的配置(比如Android),与其他工具的比较,或者如何解决常见错误等。需要确保问题相关且有价值,引导用户进一步学习。 现在要确保回答符合用户给的系统级指令:行内公式用$,独立公式用$$,正确的中文,结构清晰。但这个问题可能不需要数学公式,所以可能不需要处理这部分。但需要检查是否有地方可能需要用到LaTeX,比如如果有命令中的变量可能需要用行内代码块而不是LaTeX。可能用户提供的引用中有代码示例,需要用代码块展示,比如编译命令和示例程序。 另外,引用标注要正确,用户提供的三个引用,在回答中适当的地方标注,比如在编译命令后面加上[^1],在Android配置部分提到引用[^2],官方文档引用[^3]。 现在组织回答的结构: 1. 配置步骤:分编译器,GCC/Clang,CMake,Android Studio(引用[2]) 2. 示例代码和运行:展示一个有内存错误的代码,编译命令,运行后的ASan输出示例 3. 输出解读:解释常见的错误信息 4. 注意事项:性能、兼容性、调试符号等 5. 相关问题 需要确保各部分清晰,代码示例正确,命令准确。比如示例代码可能是一个数组越界访问: 比如: int main() { int *arr = malloc(5 * sizeof(int)); arr[5] = 10; // 越界 free(arr); return 0; } 编译命令是gcc -fsanitize=address -g -o example example.c,然后运行./example,ASan会报告堆缓冲区溢出。 然后解释输出中的关键部分,比如错误类型、位置、堆栈跟踪等。 在注意事项里,提到不要与其他sanitizer混用,比如同时使用LeakSanitizer可能没问题,但和Valgrind可能不行。另外,性能开销大约2倍,所以生产环境不建议使用。 最后生成的相关问题可能需要包括如何结合ASan和其他工具,在特定环境如Android中的使用,或者如何处理ASan报告的错误等。</think>### 如何使用AddressSanitizer进行内存错误检测 #### 1. 配置与编译 AddressSanitizerASan)通过编译器标志启用,支持GCC(≥4.8)和Clang(≥3.1)。以下为不同场景的配置方法: - **GCC/Clang命令行** 添加编译选项 `-fsanitize=address` 和调试符号 `-g`: ```bash gcc -fsanitize=address -g -o example example.c # 使用GCC clang -fsanitize=address -g -o example example.c # 使用Clang ``` - **CMake项目** 在 `CMakeLists.txt` 中添加: ```cmake add_compile_options(-fsanitize=address) add_link_options(-fsanitize=address) ``` - **Android应用** 在 `build.gradle` 中启用ASan: ```groovy android { defaultConfig { externalNativeBuild { cmake { arguments "-DANDROID_STL=c++_shared" cppFlags "-fsanitize=address" } } } } ``` --- #### 2. 示例代码与运行 以下C程序包含**堆缓冲区溢出**错误: ```c #include <stdlib.h> int main() { int *arr = malloc(5 * sizeof(int)); arr[5] = 10; // 越界写入(合法索引为0-4) free(arr); return 0; } ``` 编译并运行: ```bash gcc -fsanitize=address -g -o example example.c ./example ``` ASan输出示例: ``` ================================================================= ==ERROR: AddressSanitizer: heap-buffer-overflow WRITE of size 4 at 0x60200000eff4 thread T0 #0 0x400a56 in main example.c:5 #1 0x7f2b1d3d082f in __libc_start_main ... 0x60200000eff4 is located 4 bytes after 20-byte region [0x60200000efe0,0x60200000eff4) allocated by thread T0 here: #0 0x7f2b1d7b5b50 in malloc #1 0x400a3a in main example.c:4 ... ``` --- #### 3. 错误类型解析 ASan检测以下常见错误: | 错误类型 | 示例场景 | |-----------------------|------------------------------| | 堆溢出 | `arr[5] = 10`(分配5元素数组)| | 栈溢出 | 局部变量越界访问 | | 使用已释放内存(UAF) | `free(arr); arr[0] = 1;` | | 内存泄漏 | 未释放`malloc`分配的内存 | --- #### 4. 注意事项 1. **兼容性** - 避免与Valgrind等工具同时使用[^3] - 部分嵌入式环境可能不支持 2. **性能影响** 运行时开销约2倍,**生产环境禁用** 3. **调试符号** 必须添加 `-g` 选项以显示代码行号 4. **优化级别** 建议使用 `-O1` 以平衡检测精度与性能 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值