ASAN使用教程
更新时间:2025/10/15
在Gitcode上查看源码

ASAN使用教程

1. 需要在单板上配置的环境变量

shell
export ASAN_OPTIONS=halt_on_error=0:log_path=/home/asan/log:detect_leaks=1
export UBSAN_OPTIONS=halt_on_error=0:log_path=/home/asan/log:detect_leaks=1
export LSAN_OPTIONS=exitcode=0:use_unaligned=1:leak_check_at_exit=1:verbosity=1:log_threads=1
export PATH=$PATH:/home/asan
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/asan

2. 修改编译选项

增加如下选项:

shell
-fsanitize=address -fsanitize=leak -fsanitize=undefined -fsanitize-recover=address,all -fno-var-tracking -fno-omit-frame-pointer -fno-stack-protector -static-libasan

3. 导入ASAN库文件

路径:/opt/hcc_arm64le/aarch64-linux-gnu/lib64/

需要两个文件:libubsan.so.0.0.0libasan.so.4.0.0

修改名称为libubsan.so.0libasan.so.4,放到单板/home/asan目录下。

4. 修改App注册信号处理函数

因为ASAN内存泄漏只在进程结束时检查,所以常驻进程需要增加退出接口。

c
int __lsan_do_leak_check();

LOCAL void redfish_exit_for_asan(int sig)
{
    debug_log(DLOG_ERROR, "start appname exit for asan!");
    __lsan_do_leak_check();
    vos_task_delay(5000UL);
    exit(0);
    debug_log(DLOG_ERROR, "end appname exit for asan!");
}

在init函数中增加注册:signal(44, redfish_exit_for_asan);

5. 编译App

需要使用带符号表的App进行检测。

6. 确认App执行权限

内存泄漏检测会用到ptrace连接到线程进行内存泄漏检测。

ptrace当前rtos权限限制,只有root用户有权限使用。所以要去掉App降权限操作。

7. 导入App到单板,使用root用户执行

复现问题,使用如下命令启动App:

bash
LD_PRELOAD=/home/asan/libasan.so.4:/home/asan/libubsan.so.0:$LD_LIBRARY_PATH ./kvm_vmm &

8. 触发内存泄漏检测

执行:kill -s 44 pid 触发内存泄漏检测。

9. 查看日志

/home/asan/目录下查看日志,查看log.pid文件。

其他编译选项说明:

如下两个参数同时使用,会一个输出到log日志,一个输出到当前窗口:

shell
-fsanitize=address
-fsanitize=undefined

如下选项链接静态库使用:

shell
-static-libasan

其他说明

规避SEGV错误

增加环境变量:handle_segv=0

shell
export ASAN_OPTIONS=halt_on_error=0:use_sigaltstack=0:fast_unwind_on_fatal=1:fast_unwind_on_check=1:fast_unwind_on_malloc=1:malloc_context_size=15:dump_instruction_bytes=1:quarantine_size=4194304:log_path=/mbsc/maintain_log/asan.log:allow_user_segv_handler=1:intercept_tls_get_addr=0:detect_leaks=0:suppressions=$SUPP_FILE:print_suppressions=0:alloc_dealloc_mismatch=0:use_unaligned=1:new_delete_type_mismatch=0

ASAN_OPTIONS参数说明:

  • ASAN_OPTIONS是Address-Sanitizer的运行选项环境变量
  • log_path是执行检查报告的输出路径
  • alloc_dealloc_mismatch:申请内存与释放内存不匹配,=0表示关闭
  • new_delete_type_mismatch:new与delete申请释放类型不匹配,例如new[]的内存用delete释放,=0表示关闭
shell
export LSAN_OPTIONS=exitcode=0:use_unaligned=1

LSAN_OPTIONS参数说明:

LSAN_OPTIONS是LeakSanitizer运行选项的环境变量,而LeakSanitizer是ASAN的内存泄漏检测模块。

App实践示例

需要的编译选项

shell
-fsanitize=address -fsanitize-recover=address,all -fno-var-tracking -fno-omit-frame-pointer -fno-stack-protector -O0

注意: -fsanitize-recover这个选项必须加上,否则检测到一个错误就直接退出。

环境变量

shell
export ASAN_OPTIONS=halt_on_error=false:detect_leaks=1

也可以指定日志路径:

shell
export ASAN_OPTIONS=halt_on_error=false:detect_leaks=1:log_path=/home/asan

说明: halt_on_error是配合-fsanitize-recover一起起作用的,保证检测到错误后继续运行。

执行方式

在编译完成后,如果使用CLion执行会直接报错退出,需要用命令行执行,才能正确显示ASAN信息。

检测classtree中的内存泄漏示例

进行了10次加载与释放,每次泄漏了121个objects,242bytes的内存。最后定位到是hashtable没有释放内存。

提示: g_hash_table_new_full如果使用int作为key,有两种写法:

  • 一种是g_direct_hash+GINT_TO_POINTER(这种不需要释放内存)
  • 一种是g_int_hash(需要释放)

使用ASAN库

使用的时候,需要指定ASAN的lib库:

shell
LD_PRELOAD=/usr/lib/gcc/x86_64-linux-gnu/9/libasan.so ./security_policy

所有环境变量

shell
ASAN_OPTIONS=halt_on_error=false:detect_leaks=1;LD_PRELOAD=/usr/lib/gcc/x86_64-linux-gnu/9/libasan.so