使用 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 版本。

对于其他设备,请联系您的制造商获取操作系统的 HWASan 版本(如果可用),或使用仅软件的 ASan 工具。

在您的项目中使用共享 C++ 标准库

由于已知问题,当使用 libc++_static 时,ASan 与 C++ 异常处理不兼容。当使用 libc++_shared 时,不会出现此问题。

HWASan 有其自己的运算符 newdelete 实现,如果标准库静态链接到项目中,则无法使用它们。

要更改此设置,请参阅本文档的 链接 C++ 标准库 部分。

启用帧指针生成

HWASan 和 ASan 使用基于快速帧指针的展开器来生成内存分配和释放事件的堆栈跟踪信息。这意味着您必须在 C++ 编译器设置中启用帧指针生成才能使用这些功能。也就是说,您需要禁用帧指针省略优化。

要更改此设置,请参阅本文档的 启用帧指针生成 部分。

配置 Visual Studio 项目以使用 HWASan 或 ASan

启用 HWASan 或 ASan

要启用 HWASan 或 ASan,请转到项目属性页中项目的配置属性 > 常规

The Visual Studio Solution Explorer properties menu for the current
project.

图 1:Visual Studio 解决方案资源管理器窗口中项目的属性选项。

The project Property Pages dialog with General properties shown, and Address
Sanitizer settings highlighted.

图 2:常规项目属性中的Address Sanitizer (ASan) 设置。

要为您的项目启用 HWASan,请将Address Sanitizer (ASan) 设置更改为硬件 ASan 已启用 (fsanitize=hwaddress)

要为您的项目启用 ASan,请将Address Sanitizer (ASan) 设置更改为ASan 已启用 (fsanitize=address)

启用帧指针生成

帧指针生成由省略帧指针 C/C++ 编译器设置控制,可以在项目属性页下的配置属性 > C/C++ > 优化中找到。

The project Property Pages dialog with C/C++ Optimization properties shown,
and Omit Frame Pointer settings
highlighted.

图 3:查找省略帧指针设置的位置。

使用 HWASan 或 ASan 时,将省略帧指针设置设置为否 (-fno-omit-frame-pointer)

以共享库模式链接 C++ 标准库

C++ 标准库的链接器模式设置可以在项目属性页下的配置属性 > 常规中的项目默认值部分找到。

The project Property Pages dialog with the General category selected, and the
Use of STL setting
highlighted.

图 4:查找 C++ 标准库的链接器模式设置的位置。

使用 HWASan 或 ASan 时,将STL 的使用设置为使用 C++ 标准库 (.so)。此值将 C++ 标准库链接到您的项目作为共享库,这是 HWASan 和 ASan 正确运行所必需的。

创建用于 Address Sanitizer 的构建配置

如果您希望临时使用 HWASan 或 ASan,则可能不想仅为其使用创建一个新的构建配置。如果您的项目很小、您正在探索该功能或响应在测试期间发现的问题,则可能就是这种情况。

但是,如果您发现它有用并计划定期使用它,则可以考虑为 HWASan 或 ASan 创建一个新的构建配置,如 茶壶示例 中所示。例如,如果定期运行 Address Sanitizer 作为单元测试的一部分,或在游戏的隔夜冒烟测试期间,您可能会这样做。

如果您有一个大型项目,该项目使用了大量不同的第三方库,并且通常将它们与 C++ 标准库静态链接,那么创建单独的构建配置可能特别有用。专用构建配置可以帮助确保您的项目设置始终保持准确。

要创建构建配置,请在项目的**属性页**中,点击**配置管理器…**按钮,然后打开**活动解决方案配置**下拉列表。然后选择**<新建…>**,并使用适当的名称(例如,已启用 HWASan)创建一个新的构建配置。