概述
AddressSanitizer
(ASan
)最初由Google
开发并开源,是LLVM/Clang
编译器工具链的一部分- 它的核心目标是检测内存错误(如缓冲区溢出、释放后使用等),并通过 影子内存(
Shadow Memory
) 和 运行时插桩(Instrumentation
) 实现高效检测 Windows
相关- 微软从
Visual Studio 2019 (v16.9)
开始,将ASan
功能移植到MSVC
编译器 中 - 目前检测不了内存泄露
- 微软从
Windows平台支持
关于Visual Studio
Visual Studio 2019 v16.9+
:原生集成ASan
,无需额外安装- 旧版本
VS
(如2017
):需手动安装ASan
插件
Clang for windows
- 需使用
Clang-cl
工具链,支持ASan
但配置复杂
局限
- 不支持动态库(
DLL
)的ASan
插桩 - 某些
API
(如_aligned_malloc
)可能无法被完全跟踪
启用ASan
检测内存泄漏(Visual Studio
)
步骤1:启用ASan
- 打开项目属性 →
C/C++
→General
→Enable Address Sanitizer
→Yes
- 确保生成配置为
Debug
(ASan
依赖调试符号)
步骤2:配置泄漏检测
- 设置环境变量
ASAN_OPTIONS
(可选):detect_leaks=1
:强制启用泄漏检测(默认已开启)malloc_context_size=20
:记录泄漏时的堆栈深度
1 |
set ASAN_OPTIONS=detect_leaks=1 |
步骤3:编译并运行程序
- 直接运行程序(
F5
),ASan
会在程序退出时输出泄漏报告
VS
具体情况
- 按上述步骤,
Visual studio
集成的ASan
可以检测到内存的越界访问 - 按上述步骤,
Visual studio
集成的ASan
检测不到内存的泄露- 可能功能在开发中,可以确定,
2024
年底的时候,这功能还没有添加
- 可能功能在开发中,可以确定,
Unix
、里面使用ASan
Debian
- 验证环境是
debian12
系统
环境准备
- 安装支持
asan
的编译器
1 2 |
sudo apt update sudo apt install gcc clang |
- 查看版本
1 2 |
gcc --version clang --version |
- 安装调试符号和依赖库
1 2 3 |
sudo apt install libasan6 # Debian 12 对应 libasan8 sudo apt install libasan8 |
编译启用ASan
bash
1 2 |
gcc -fsanitize=address -g -O0 -o test test.c # C 语言 clang++ -fsanitize=address -g -O0 -o test test.cpp # C++ |
makefile
1 2 3 4 5 6 7 8 |
CC = gcc CFLAGS = -fsanitize=address -g -O0 -Wall TARGET = my_program all: $(TARGET) $(TARGET): main.c utils.c $(CC) $(CFLAGS) -o $@ $^ |
运行时配置
- ASan 默认不启用内存泄漏检测,需通过环境变量显式开启
1 |
export ASAN_OPTIONS="detect_leaks=1:halt_on_error=0:log_path=./asan.log" |
- 我自己仅仅用了
1 |
export ASAN_OPTIONS="detect_leaks=1" |
- 动态库路径(
Debian
特定问题)- 若遇到动态库加载错误,手动指定
ASan
运行时库路径: - 不过我没有遇到这个问题,所以没有执行下面这一句
- 若遇到动态库加载错误,手动指定
1 |
export LD_PRELOAD=$(gcc -print-file-name=libasan.so) |
测试代码
1 2 3 4 5 6 7 |
#include <stdlib.h> int main() { malloc(1024); return 0; } |
效果
gcc具体情况
- 可以检测到内存越界的情况
- 可以检测到内存泄露
macOS
里面使用ASan
XCode
xcode
里面继承了ASan
- 启用步骤如下:
Product
- `
Scheme
-Edit Scheme
Run
-Diagnostics
Address Sanitizer
XCode
具体情况
xcode
里面可以检测到内存的越界访问xcode
里面,可以用Product
-Analyze
提示相关内存泄露信息
clang
- 使用
bash
1 |
clang -fsanitize=address -g memory-leak.c ; ASAN_OPTIONS=detect_leaks=1 ./a.out |
clang具体情况
- 我这边是
arm
芯macOS
- 目前显示:
detect_leaks is not supported on this platform
解读内存泄漏报告
示例
1 2 3 4 5 6 7 |
==12345==ERROR: LeakSanitizer: detected memory leaks Direct leak of 40 byte(s) in 1 object(s) allocated from: #0 0x7ff8d1f5a1d8 in malloc (asan_rtl.dll+0x1a1d8) #1 0x7ff6a3c51234 in main() src\leak_example.cpp:5 SUMMARY: AddressSanitizer: 40 byte(s) leaked in 1 allocation(s). |
泄露类型
Direct leak
:直接未释放的内存Indirect leak
:因其他泄漏导致无法释放(如指针丢失)
高级配置
排除误报
- 忽略特定泄漏:在代码中添加:
1 2 |
#include <sanitizer/lsan_interface.h> __lsan_ignore_object(ptr); // 忽略ptr指向的内存块 |
- 过滤全局变量:确保全局变量使用
volatile
或const
,避免被误判
输出到文件
- 设置
ASAN_OPTIONS
:
1 |
set ASAN_OPTIONS=log_path=asan.log |
- 报告将保存到
asan.log.12345
(PID
后缀)
实时检测(非退出时)
- 手动触发泄漏检查:
1 2 |
#include <sanitizer/lsan_interface.h> __lsan_do_recoverable_leak_check(); // 在代码中主动检查 |
内存泄露检测原理
概述
ASan
在Windows
上通过LeakSanitizer
(LSan
) 检测内存泄漏,其核心机制如下:
1 内存分配追踪
- 拦截分配函数:
- 替换
malloc
、calloc
、realloc
和free
,记录每个分配的内存块及其调用栈
- 替换
- 维护分配表:
- 全局哈希表保存所有未释放的内存块信息(地址、大小、分配堆栈)
2 泄露判定
- 程序退出时检查:
- 在程序正常退出或崩溃时,遍历分配表,标记所有未被释放的内存块为泄漏
- 忽略全局变量:
- 通过扫描全局区段,排除全局变量持有的内存(需调试符号)
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Macos开发问题:aarch64架构宏不识别06/25
- ♥ Shell 语法记述 第三篇09/05
- ♥ Shell 语法记述 第一篇09/04
- ♥ Macos蓝牙相关05/31
- ♥ COM组件_303/07
- ♥ lldb调试04/21