一、它能抓到什么#
// 1. 堆越界访问(Heap buffer overflow)
void heap_oob() {
auto* arr = new int[10];
arr[10] = 42; // ASan 在这里崩溃,告诉你越界了
delete[] arr;
}
// 2. 栈越界访问(Stack buffer overflow)
void stack_oob() {
int arr[10];
arr[10] = 42; // ASan 捕获
}
// 3. Use-After-Free(释放后使用)
void use_after_free() {
auto* p = new int(42);
delete p;
*p = 0; // ASan 捕获:Address 0x... is a wild pointer
}
// 4. Double-Free
void double_free() {
auto* p = new int(42);
delete p;
delete p; // ASan 捕获:double free
}
二、用法#
# 编译:加入 sanitize 标志
g++ -fsanitize=address -fno-omit-frame-pointer -g -O1 -o test test.cpp
# 运行(不用任何额外命令,直接运行即可)
./test
# 出错了会类似这样输出:
# ==============================================================
# ==12345==ERROR: AddressSanitizer: heap-buffer-overflow
# WRITE of size 4 at 0x602000000014 thread T0
# #0 0x400b12 in heap_oob() test.cpp:4
# #1 0x400bf1 in main test.cpp:10
# #2 0x7f1234567890 in __libc_start_main
#
# 0x602000000014 is located 0 bytes after 40-byte region
# allocated by thread T0 here:
# #0 0x7f123456abcd in operator new[](unsigned long)
# #1 0x400adf in heap_oob() test.cpp:3
#
# SUMMARY: AddressSanitizer: heap-buffer-overflow test.cpp:4
# ==============================================================
# 关键信息:
# heap-buffer-overflow → 堆越界
# test.cpp:4 → 第 4 行出了问题
# 0 bytes after 40-byte region → 在 40 字节分配区域之后越界了 0 字节(正好最后一个 int)
三、和你的两个项目相关的例子#
// SimpleAsyncLogger 中可能出现的 Use-After-Free
// ring_buffer.cpp 中的无锁队列
void producer_race_example() {
uint8_t* buffer = new uint8_t[1024];
std::thread producer([&] {
// 假设这里操作 buffer
buffer[0] = 1;
});
std::thread consumer([&] {
// 假设这里也操作 buffer
buffer[0] = 2;
});
producer.join();
consumer.join();
// ⚠️ 如果 consumer 删除了 buffer 而 producer 还在用 → ASan 帮你抓到
// 编译时带上 -fsanitize=address 就能自动检测这种问题
}
// ScoreMaster 中的 DMA-BUF fd 泄漏
void dma_buf_leak() {
// 如果忘记 close DMA buffer 的 fd
// ASan 不会直接捕获(因为 fd 是内核资源)
// 但堆上的 fd 包装对象泄漏了 ASan 是能看到的
}
四、性能影响#
ASan 开启后:
运行速度:慢约 2 倍
内存占用:多约 2-3 倍
所以只在测试/CI 构建中开启,生产环境关闭。
推荐:CMake 中按构建类型启用
# CMakeLists.txt
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
endif()