使用 Address Sanitizer 對記憶體毀損情形進行偵錯

本文說明如何在使用 AGDE 時啟用特殊偵錯工具。這些工具可找出難以診斷的記憶體毀損情形,並覆寫錯誤。

HWAddress Sanitizer 和 Address Sanitizer

HWAddress Sanitizer (HWASan) 和 Address Sanitizer (ASan) 是記憶體毀損偵錯工具,可偵測記憶體毀損情形並覆寫錯誤,例如以下情形:

  • 堆疊緩衝區溢位和反向溢位
  • 堆積緩衝區溢位和反向溢位
  • 超出範圍的堆疊使用情形
  • 重複釋放和野釋放錯誤
  • 回傳後的堆疊使用情形 (僅限 HWASan)

建議您僅在偵錯或執行自動化測試時,才啟用 HWASan 或 ASan。這些工具雖然很有效,但使用時可能導致效能降低。

執行階段行為

HWASan 和 ASan 啟用時,會自動檢查整個應用程式執行階段的記憶體毀損情形。

如果偵測到記憶體錯誤,應用程式會因 SIGBART (訊號取消) 錯誤異常終止,並將詳細訊息顯示在 Logcat。訊息也會寫入 /data/tombstones 下的檔案。

錯誤訊息應如下所示:

ERROR: HWAddressSanitizer: tag-mismatch on address 0x0042a0826510 at pc 0x007b24d90a0c
WRITE of size 1 at 0x0042a0826510 tags: 32/3d (ptr/mem) in thread T0
    #0 0x7b24d90a08  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x2a08)
    #1 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)
    #2 0x7b8f1db364  (/apex/com.android.art/lib64/libart.so+0x18f364)
    #3 0x7b8f2ad8d4  (/apex/com.android.art/lib64/libart.so+0x2618d4)

0x0042a0826510 is located 0 bytes to the right of 16-byte region [0x0042a0826500,0x0042a0826510)
allocated here:
    #0 0x7b92a322bc  (/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so+0x212bc)
    #1 0x7b24d909e0  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x29e0)
    #2 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)

必要條件

安裝 Android 作業系統的 HWASan 版本

如要使用 HWASan,請按照 HWASan 說明文件中的設定操作說明,安裝 Google Pixel 裝置適用的 Android 作業系統 HWASan 版本。

若是其他裝置,請與製造商聯絡,取得該 OS 的 HWASan 版本 (如有),或使用軟體專用 ASan 工具。

在專案中使用共用 C++ 標準程式庫

由於某項已知問題的影響,使用 libc++_static 時,ASan 目前無法處理 C++ 例外狀況。使用 libc++_shared 時則不會發生這個問題。

HWASan 擁有專屬的運算子 newdelete 實作方法,如果標準程式庫是靜態連結至專案,就無法使用這些方法。

如要變更這項設定,請參閱本文件中的連結 C++ 標準程式庫相關說明。

啟用影格指標產生功能

HWASan 與 ASan 可使用快速影格指標型解開器,為記憶體配置和取消配置事件產生堆疊追蹤資訊。這代表您必須在 C++ 編譯器設定中啟用影格指標產生功能,才能使用這些功能。您也需要停用影格指標省略最佳化功能。

如要變更這項設定,請參閱本文件的「啟用影格指標產生功能」一節。

設定 Visual Studio 專案以使用 HWASan 或 ASan

啟用 HWASan 或 ASan

如要啟用 HWASan 或 ASan,請在專案的「Property Pages」中,依序點選「Configuration Properties」>「General」

目前專案在 Visual Studio 中的「Solution Explorer」屬性選單。

圖 1:專案在 Visual Studio「Solution Explorer」視窗中的「Properties」選項。

專案「Property Pages」對話方塊中的「General」屬性,並醒目顯示「Address Sanitizer (ASan)」設定。

圖 2:一般專案屬性中的「Address Sanitizer (ASan)」設定。

如要為專案啟用 HWASan,請將「Address Sanitizer (ASan)」設定變更為「Hardware ASan Enabled (fsanitize=hwaddress)」

如要為專案啟用 ASan,請將「Address Sanitizer (ASan)」設定變更為「ASan Enabled (fsanitize=address)」

啟用影格指標產生功能

如要控管影格指標產生功能,需使用「Omit Frame Pointer」C/C++ 編譯器設定。在專案的「Property Pages」對話方塊中,依序選取「Configuration Properties」>「C/C++」>「Optimization」,即可存取這項設定。

專案「Property Pages」對話方塊的 C/C++「Optimization」屬性,並醒目顯示「Omit Frame Pointer」設定。

圖 3:「Omit Frame Pointer」設定的位置。

使用 HWASan 或 ASan 時,請將「Omit Frame Pointer」設定設為「No (-fno-omit-frame-pointer)」

在共用程式庫模式中連結 C++ 標準程式庫

在專案「Property Pages」對話方塊中,依序點選「Configuration Properties」>「General」,即可在「Project Defaults」部分找到 C++ 標準程式庫的連結器模式設定。

專案「Property Pages」對話方塊,已選取「General」類別,並醒目顯示「Use of STL」設定。

圖 4:C++ 標準程式庫連結器模式設定的位置。

使用 HWASan 或 ASan 時,請將「Use of STL」設為「Use C++ Standard libraries (.so)」。這個值會以「共用程式庫」的形式將 C++ 標準程式庫連結至專案,這是讓 HWASan 與 ASan 正常運作的必要步驟。

針對 Address Sanitizer 使用情形建立建構設定

如果您偏向「暫時」使用 HWASan 或 ASan,就不建議專為這項用途建立新的建構設定。當專案規模較小,或是您單純在瞭解這項功能或處理測試期間發現的問題時,就可能屬於這種情況。

不過,如果覺得這項功能很實用,且預計經常使用,則建議您考慮為 HWASan 或 ASan 建立新的建構設定,如 Teapot 範例所示。舉例來說,如果您會在單元測試或遊戲的整晚冒煙測試中定期執行 Address Sanitizer,就可以採用這種做法。

如果您的大型專案使用大量不同的第三方程式庫,而且這些程式庫通常是靜態連結至 C++ 標準程式庫,那另外建立建構設定就可能特別實用。專屬建構設定可隨時確保專案設定準確無誤。

如要建立建構設定,請按一下專案「Property Pages」中的「Configuration Manager…」按鈕,然後開啟「Active solution configuration」下拉式選單。接著請選取 ,使用適當名稱 (例如「HWASan enabled」) 建立新的建構設定。