C++查找bug之利器AddressSanitizer的配置
AddressSanitizer (ASan) 是查找c++程序错误的神器。它是一种编译器和运行时技术,它公开了许多误报率为零的难以发现的 bug:
- alloc/dealloc 不匹配和 new/delete 类型不匹配
- 分配对堆来说太大
- calloc 溢出和 alloca 溢出
- 重复释放和释放后使用
- 全局变量溢出
- 堆缓冲区溢出
- 对齐值对齐无效
- memcpy 和 strncat 参数重叠
- 堆栈缓冲区溢出和下溢
- return 后使用堆栈和限定作用域后使用
- 在内存中毒后使用内存
从 Visual Studio 2019 版本 16.9 开始,Microsoft C/C++ 编译器 (MSVC) 和 IDE 支持AddressSanitizer清理器。关于AddressSanitizer的详细介绍请查看微软官方对它的介绍https://learn.microsoft.com/zh-cn/cpp/sanitizers/asan?view=msvc-170
配置条件:win11系统, clion c++语言,msvc工具链,debug模式
cmakelists.txt设置如下:
cmake_minimum_required(VERSION 4.0)
project(AddressSanitizer_test)
set(CMAKE_CXX_STANDARD 20)
add_executable(test main.cpp)
# 启用AddressSanitizer
target_compile_options(test PRIVATE -fsanitize=address)
# 建议同时添加以下标志以获得更清晰的堆栈跟踪信息:cite[4]:cite[8]
# target_compile_options(test PRIVATE -fno-omit-frame-pointer -O1)
# 链接AddressSanitizer所需的库:cite[1]:cite[2]
target_link_directories(test PRIVATE
"H:/Visual_Studio_2022/VC/Tools/MSVC/14.43.34808/bin/Hostx64/x64"
"H:/Visual_Studio_2022/VC/Tools/MSVC/14.43.34808/lib/x64"
)
target_link_libraries(test PRIVATE
clang_rt.asan_dynamic-x86_64
clang_rt.asan_dynamic_runtime_thunk-x86_64)
target_link_options(test PRIVATE
/wholearchive:clang_rt.asan_dynamic_runtime_thunk-x86_64.lib)
测试代码
#include <iostream>
int main() {
// 动态分配一个整数数组
int *array = new int[10];
// 故意在数组边界外写入,触发堆缓冲区溢出
array[10] = 123; // 错误:有效索引为0-9,10是越界访问
// 释放内存
delete[] array;
return 0;
}
运行后AddressSanitizer给出的报告:
=================================================================
==13260==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x1270e9ca04f8 at pc 0x7ff6094f10df bp 0x006fff14fc50 sp 0x006fff14fc58
WRITE of size 4 at 0x1270e9ca04f8 thread T0
#0 0x7ff6094f10de in main E:\coding\cppcode\AddressSanitizer_test\main.cpp:8
#1 0x7ff6094f2a78 in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
#2 0x7ff6094f29c1 in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
#3 0x7ff6094f287d in __scrt_common_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:330
#4 0x7ff6094f2aed in mainCRTStartup D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp:16
#5 0x7ffb420a259c (C:\Windows\System32\KERNEL32.DLL+0x18001259c)
#6 0x7ffb42d4af37 (C:\Windows\SYSTEM32\ntdll.dll+0x18005af37)
0x1270e9ca04f8 is located 0 bytes after 40-byte region [0x1270e9ca04d0,0x1270e9ca04f8)
allocated by thread T0 here:
#0 0x7ff6094f1c5e in operator new[](unsigned __int64) D:\a\_work\1\s\src\vctools\asan\llvm\compiler-rt\lib\asan\asan_win_new_array_thunk.cpp:41
#1 0x7ff6094f1079 in main E:\coding\cppcode\AddressSanitizer_test\main.cpp:5
#2 0x7ff6094f2a78 in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
#3 0x7ff6094f29c1 in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
#4 0x7ff6094f287d in __scrt_common_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:330
#5 0x7ff6094f2aed in mainCRTStartup D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp:16
#6 0x7ffb420a259c (C:\Windows\System32\KERNEL32.DLL+0x18001259c)
#7 0x7ffb42d4af37 (C:\Windows\SYSTEM32\ntdll.dll+0x18005af37)
SUMMARY: AddressSanitizer: heap-buffer-overflow E:\coding\cppcode\AddressSanitizer_test\main.cpp:8 in main
Shadow bytes around the buggy address:
0x1270e9ca0200: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 07 fa
0x1270e9ca0280: fa fa 00 00 00 00 00 01 fa fa 00 00 00 00 00 04
0x1270e9ca0300: fa fa 00 00 00 00 00 02 fa fa 00 00 00 00 01 fa
0x1270e9ca0380: fa fa 00 00 00 00 07 fa fa fa 00 00 00 00 00 01
0x1270e9ca0400: fa fa 00 00 00 00 07 fa fa fa 00 00 00 00 07 fa
=>0x1270e9ca0480: fa fa 00 00 00 00 06 fa fa fa 00 00 00 00 00[fa]
0x1270e9ca0500: fa fa 00 00 00 00 00 fa fa fa fa fa fa fa fa fa
0x1270e9ca0580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1270e9ca0600: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1270e9ca0680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1270e9ca0700: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==13260==ABORTING
Process finished with exit code 1
从这个报告可以看出是什么错误引起的:
==1088==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x113177ba04f8 at pc 0x7ff7d49f10df bp 0x0018dadbfc20 sp 0x0018dadbfc28 WRITE of size 4 at 0x113177ba04f8 thread T0
-
错误类型:
heap-buffer-overflow- 堆缓冲区溢出,即访问了堆上分配的缓冲区的边界之外的内存 -
进程ID: 1088
-
内存地址:
0x113177ba04f8- 发生溢出的具体内存地址 -
操作:
WRITE of size 4- 进行了4字节的写入操作(对应int类型) -
线程: T0 (主线程)
调用堆栈跟踪
#0 0x7ff7d49f10de in main E:\coding\cppcode\AddressSanitizer_test\main.cpp:8
关键信息: 错误发生在你的代码 main.cpp 第8行。在你的测试代码中,这对应:
arr[10] = 42; // 第8行 - 堆缓冲区溢出
其他堆栈帧 (#1-#7) 是C++运行时和Windows系统的启动代码,对于调试来说不太重要。
......
这个报告展示了AddressSanitizer强大的诊断能力 - 它不仅告诉你发生了错误,还精确指出了错误的位置、内存分配的历史以及内存布局的详细信息。
更多推荐


所有评论(0)