Linux下內存檢測工具:asan
ASAN(Address-Sanitizier)早先是LLVM中的特性,後被加入GCC 4.8,在GCC 4.9後加入對ARM平臺的支持。因此GCC 4.8以上版本使用ASAN時不需要安裝第三方庫,通過在編譯時指定編譯CFLAGS即可打開開關。
1、編譯選項
1.1 Gcc編譯選項
# -fsanitize=address:開啓內存越界檢測
# -fsanitize-recover=address:一般後臺程序爲保證穩定性,不能遇到錯誤就簡單退出,而是繼續運行,採用該選項支持內存出錯之後程序繼續運行,需要疊加設置ASAN_OPTIONS=halt_on_error=0纔會生效;若未設置此選項,則內存出錯即報錯退出
ASAN_CFLAGS += -fsanitize=address -fsanitize-recover=address
# -fno-stack-protector:去使能棧溢出保護
# -fno-omit-frame-pointer:去使能棧溢出保護
# -fno-var-tracking:默認選項爲-fvar-tracking,會導致運行非常慢
# -g1:表示最小調試信息,通常debug版本用-g即-g2
ASAN_CFLAGS += -fno-stack-protector -fno-omit-frame-pointer -fno-var-tracking -g1
1.2 Ld鏈接選項
ASAN_LDFLAGS += -fsanitize=address -g1
如果使用gcc鏈接,此處可忽略。
2、ASAN運行選項
2.1 ASAN_OPTIONS設置
ASAN_OPTIONS是Address-Sanitizier的運行選項環境變量。
# halt_on_error=0:檢測內存錯誤後繼續運行
# detect_leaks=1:使能內存泄露檢測
# malloc_context_size=15:內存錯誤發生時,顯示的調用棧層數爲15
# log_path=/home/xos/asan.log:內存檢查問題日誌存放文件路徑
# suppressions=$SUPP_FILE:屏蔽打印某些內存錯誤
export ASAN_OPTIONS=halt_on_error=0:use_sigaltstack=0:detect_leaks=1:malloc_context_size=15:log_path=/home/xos/asan.log:suppressions=$SUPP_FILE
除了上述常用選項,以下還有一些選項可根據實際需要添加:
# detect_stack_use_after_return=1:檢查訪問指向已被釋放的棧空間
# handle_segv=1:處理段錯誤;也可以添加handle_sigill=1處理SIGILL信號
# quarantine_size=4194304:內存cache可緩存free內存大小4M
ASAN_OPTIONS=${ASAN_OPTIONS}:verbosity=0:handle_segv=1:allow_user_segv_handler=1:detect_stack_use_after_return=1:fast_unwind_on_fatal=1:fast_unwind_on_check=1:fast_unwind_on_malloc=1:quarantine_size=4194304
2.2 LSAN_OPTIONS設置
LSAN_OPTIONS是LeakSanitizier運行選項的環境變量,而LeakSanitizier是ASAN的內存泄漏檢測模塊,常用運行選項有:
# exitcode=0:設置內存泄露退出碼爲0,默認情況內存泄露退出碼0x16
# use_unaligned=4:4字節對齊
export LSAN_OPTIONS=exitcode=0:use_unaligned=4
3、總結
實際開發環境中,可能存在gcc版本低,使用asan做內存檢查時,需要鏈接libasan.so庫的情況。其次,平臺軟件通常都會內部實現一套內存操作接口,爲使用asan工具,需要替換成glibc提供的接口。此時,可以通過LD_PRELOAD環境變量解決這類問題。
export LD_PRELOAD= libasan.so.2:libprelib.so #vos_malloc --> malloc
最後,ASAN選項比較多,本文不一一羅列&解釋,讀者可自行百度!