前言
AddressSanitizer (ASAN) 是記憶體除錯利器,除了 MSVC 實做的,比較知名的元老是 Google 實做的版本。
面對一些比較基礎的記憶體問題如 buffer overflow,許多 IDE 內建的掃描即可在編輯器中提示。但面對 runtime 較為複雜如 race condition 時候才會出現的記憶體問題,就有賴 Sanitizer 動態跟蹤除錯了。
筆者最近遇到程式結束時 double free 問題,從 debugger 的 parallel stacks 只看得出來是系統在清理時遭遇到,看不出來是哪個物件,在這種情境下就很適合用 Sanitizer 來協助告知究竟是哪一行程式碼出問題。
支援的記憶體問題
微軟官方文件提到 VS 2019 (16.9) 後開始支援 Sanitizer,可以找出記憶體錯誤的種類包含:
- Alloc/dealloc mismatches and new/delete type mismatches
- Allocations too large for the heap
- calloc overflow and alloca overflow
- Double free and use after free
- Global variable overflow
- Heap buffer overflow
- Invalid alignment of aligned values
- memcpy and strncat parameter overlap
- Stack buffer overflow and underflow
- Stack use after return and use after scope
- Memory use after it’s poisoned
設定
雖然微軟文件說 CMake 專案只需要設定 "addressSanitizerEnabled": true
**,**但實際上這麼做並無法成功。
不管是用 MSVC 或是 clang,都必須要告知 compiler 與 linker 要使用 AddressSanitizer。因此在 CMake 加上:
add_compile_options(-fsanitize=address)
add_compile_options(-fno-omit-frame-pointer)
add_link_options(-fsanitize=address)
add_link_options(-fno-omit-frame-pointer)
通常來說這樣就夠了,但是直接執行的話,會遇到
這是因為該 DLL 沒有被放進 System32,因此在動態連結會出問題。
緩解方式是到 C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\bin\Hostx64\x64
把 clang_rt.asan_dbg_dynamic-x86_64.dll
複製一份到 MSVC 的 build folder 即可。
當然,不想手動複製的話,可以用 CMake install 方式:
install(FILES "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.35.32215/bin/Hostx64/x64/clang_rt.asan_dbg_dynamic-x86_64.dll" DESTINATION ${CMAKE_BINARY_DIR})
重新執行就可以看到成功抓到 bof。
備註
在 Sanitizer 整合性上面,CLion 做得比 Visual Studio 還要好,有獨立的視窗顯示跟蹤結果,JetBrains 不愧是專業 IDE 開發公司。
參考
- What’s the proper way to enable AddressSanitizer in CMake that works in Xcode
- Application crashes when using address sanitizer with MSVC
comments powered by Disqus