概述
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-DiagnosticsAddress 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所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ gcc/g++编译器03/21
- ♥ macOS应用记述一10/26
- ♥ Visual Studio:管理工程文件10/14
- ♥ Bash Shell 命令09/04
- ♥ Visual Studio:条件断点与字符串相关12/04
- ♥ Macos 实用工具记述:一07/06

