Android 中 调试和减少内存错误

Android 中 调试和减少内存错误

ASan

概述

官网连接: https://developer.android.com/ndk/guides/asan?hl=zh-cn

  • ASan API 27开始
  • HWASan(替换AScan)
    • 从 NDK r21 和 Android 10(API 级别 29)开始
    • 适用于 64 位 Arm 设备
    • 性能比AScan更好

主要功能

  • 堆栈和堆缓冲区上溢或下溢
  • 释放之后的堆使用情况
  • 超出范围的堆栈使用情况
  • 重复释放或错误释放

示例应用

示例应用展示了如何为 hwasan 配置 build 变体。

模拟出几个内存错误的问题

1. 越界访问 (Buffer Overflow/Underflow)

#### 问题描述: 当程序试图访问数组或缓冲区以外的内存时,就会发生越界访问错误。这类问题往往导致数据损坏,崩溃或安全漏洞。 #### 具体表征:

  • 程序崩溃:可能导致应用无预警地关闭。
  • 数据损坏:错误地重写了其他变量的值。
  • 安全漏洞:可能被利用执行恶意代码。

#### 示例代码:

int array[5] = {0};
int value = array[10]; // 越界读取
array[-1] = 3;        // 越界写入
2. 使用后释放 (Use After Free)

#### 问题描述: 当程序释放了一块内存后仍然尝试使用它时,就会发生使用后释放错误。这是一种非常危险的安全漏洞。 #### 具体表征:

  • 不可预知的行为:可能导致程序执行一段随机的内存操作。
  • 程序崩溃:访问被释放内存可能导致程序无法继续执行。
  • 内存损坏:可能不经意间修改了由其他部分的程序占用的内存。

#### 示例代码:

char *ptr = new char[20];
delete [] ptr; // 释放内存
strcpy(ptr, "这是错误的使用!"); // 在释放后使用内存
3. 内存泄露 (Memory Leak)

#### 问题描述: 未能释放不再使用的内存导致内存泄露。虽然它不会立即导致程序崩溃,但会随着时间推移而逐渐消耗系统资源。 #### 具体表征:

  • 内存消耗增加:随着程序的运行,预期的内存使用量会不断增加。
  • 性能降低:可用内存减少可能导致系统运行变慢,甚至出现延迟。
  • 可能的程序崩溃:如果内存泄露严重,系统最终可能耗尽内存,导致应用或系统崩溃。

#### 示例代码:

void func()
{char *ptr = new char[10]; // 分配内存// 这里应该有一些处理// 忘记释放ptr分配的内存
}

这些内存错误问题都是开发过程中应当注意避免的。常规的调试方法和一些专用工具比如Valgrind、AddressSanitizer(ASan)和上文提到的HWAddressSanitizer(HWASan)能够帮助开发者检测并解决这些内存错误。

HWASan输出日志分析

模拟HWAddressSanitizer的日志输出实际会涉及到针对具体错误调用堆栈和内存映射的信息。由于HWASan的具体日志输出会根据实际运行时的环境和错误情境有所不同,下面我将模拟几个内存错误的HWASan日志输出及关键点说明:

1. 越界访问错误
=================================================================
==12345==ERROR: HWAddressSanitizer: tag-mismatch on address 0x00b100004008 at pc 0x000000552abc
WRITE of size 4 at 0x00b100004008 tags: 1c/15 (ptr/mem) in thread T0#0 0x552abc  (/path/to/binary+0x552abc)#1 0x55678f  (/path/to/binary+0x55678f)#2 0x7f7c85dd9c  (/system/lib/hwaddress-sanitizer.so+0x5dd9c)
0x00b100004008 is located 0 bytes to the right of 8-byte region [0x00b100004000,0x00b100004008)
allocated by thread T0 here:#0 0x7f7c85ca58  (/system/lib/hwaddress-sanitizer.so+0x5ca58)#1 0x5556f4  (/path/to/binary+0x5556f4)#2 0x555979  (/path/to/binary+0x555979)
SUMMARY: HWAddressSanitizer: tag-mismatch /path/to/binary (0x552abc) WRITE 0x00b100004008
=================================================================

#### 关键点说明:

  • tag-mismatch 表示检测到内存标签不匹配,这通常提示内存访问错误。
  • WRITE of size 4 说明试图写入4个字节的数据。
  • address 0x00b100004008 at pc 0x000000552abc 显示了发生错误的内存地址和程序计数器的地址。
  • 调用堆栈(call stack)提供了错误发生时的函数调用序列。
  • 0x00b100004008 is located 0 bytes to the right of 8-byte region 说明写操作是在8字节区域的右侧进行的,这是越界访问。
2使用后释放错误

================================================================= ==12345==ERROR: HWAddressSanitizer: use-after-free on address 0x00b100004010 at pc 0x000000552efc READ of size 8 at 0x00b100004010 tags: 1c/00 (ptr/mem) in thread T0    #0 0x552efc  (/path/to/binary+0x552efc)    #1 0x556abc  (/path/to/binary+0x556abc)    #2 0x7f7c85dd9c  (/system/lib/hwaddress-sanitizer.so+0x5dd9c) 0x00b100004010 is located 0 bytes inside of 10-byte region [0x00b100004010,0x00b10000401a) freed by thread T0 here:    #0 0x7f7c85caff0  (/system/lib/hwaddress-sanitizer.so+0xcaff0)    #1 0x555999  (/path/to/binary+0x555999)    #2 0x5.#2 0x7f7c85dd9c  (/system/lib/hwaddress-sanitizer.so+0x5dd9c)
0x00b100004010 is located 0 bytes inside of 10-byte region [0x00b100004010,0x00b10000401a)
freed by thread T0 here:#0 0x7f7c85caff0  (/system/lib/hwaddress-sanitizer.so+0xcaff0)#1 0x555999  (/path/to/binary+0x555999)#2 0x556df9  (/path/to/binary+0x556df9)
previously allocated by thread T0 here:#0 0x7f7c85ca58  (/system/lib/hwaddress-sanitizer.so+0x5ca58)#1 0x5557e8  (/path/to/binary+0x5557e8)
SUMMARY: HWAddressSanitizer: use-after-free (/path/to/binary+0x552efc) READ 0x00b100004010
=================================================================

#### 关键点说明:

  • use-after-free 表示在释放后再次使用了内存,这是一种严重的错误。
  • READ of size 8 说明尝试读取8个字节的数据。
  • address 0x00b100004010 at pc 0x000000552efc 显示了被错误读取的内存地址和相关的程序计数器的地址。
  • 调用堆栈(call stack)提供了释放内存和随后错误使用该内存的函数调用序列。
  • freed by thread T0 here:previously allocated by thread T0 here: 显示了内存分配及后续释放的位置。

在分析这样的日志时,开发者需要关注堆栈跟踪来确定错误发生的上下文,并修复代码中相应的问题。日志中的内存地址、线程信息以及函数调用序列都是确定问题所在和解决问题的关键信息。在实际的开发工作中,可通过这些详尽的日志来定位问题,优化代码,并进一步强化软件的稳健性和安全性。

Arm 内存标记扩展 (MTE)

  1. 支持ARMv8.5-A及以上架构的处理器
  2. 从 Android 13 开始,部分设备支持 MTE
  3. adb shell grep mte /proc/cpuinfo 出现 Features : [...] mte则表示设备在运行时启用了 MTE

MTE vs ASan

MTE是 ARM 架构提供的硬件特性,它通过在物理内存中添加一些标记信息来辅助检测内存安全错误,它的优势在于提供硬件层面的检测,开销相较软件层面的检测方式较小,特别是在ASYNC模式下。HWASan 是一种基于软件的解决方案,通过修改编译器和运行时环境来检测内存安全问题,特别是地址错误和内存泄漏等。它是谷歌为ARM64架构设计的,针对Android操作系统进行了优化。HWASan在测试和分析阶段特别有用,因为它能提供详尽的错误报告,包括堆栈追踪和内存访问历史等。

如在支持MTE的ARMv8.5及以上架构的设备上,可以优先选用MTE

SYNC 和ASYNC异同

维度SYNC(同步模式)ASYNC(异步模式)
优化目标针对可调试性优化,适用于精确的 bug 检测工具针对 bug 报告的性能优化,偏向于低开销的内存安全检测
处理器反应在接收到违规的加载或存储指令时,会立即终止进程处理器会在到达最近的内核入口(如系统调用或计时器中断)时终止进程
错误报告返回SIGSEGV,提供内存访问和故障地址的详细信息返回SIGSEGV,但是不记录错误地址或内存访问
配合Android分配器分配器会记录每次分配和取消分配的堆栈轨迹以提供更好的错误报告不进行此操作
应用场景用作测试阶段的HWASan的更快替代方案,或生产环境中的应用出现漏洞时的安全缓解措施。对经过严格测试的代码库(已知其内存安全 bug 的密度较低)降低内存安全漏洞的生产环境

两种模式的相同点包括:
在进行硬件辅助的内存安全错误检测时,SYNC和ASYNC都可以监测到内存安全错误。一旦发现标记不匹配,两种模式均会触发处理器的响应,终止进程并返回SIGSEGV。在这两种模式下,都可以在测试阶段运用来找出内存安全bug。

给自己分配的内存打TAG

scudo 实现代码

  • setRandomTag 函数:该函数是用来为给定的指针 Ptr 设置一个随机的内存标签。
  • untagPointer 函数:这个函数会移除指针 Ptr 的内存标签
  • loadTag 函数:此函数似乎用于返回指针 Ptr 上的内存标签
  • addFixedTag 函数:这个函数用于给一个指针 Ptr 添加一个固定的标签 Tag
  • allocatorSupportsMemoryTagging 模板函数:此函数用于确定是否支持内存标记。

使用场景

  1. 内存错误检测:在分配和释放内存时为其打上Tag,可以帮助检测内存安全错误,如缓冲区溢出、使用后释放等。当一个内存区域被释放后,您可以为其分配一个新的Tag,如果之后系统尝试使用相同的旧Tag访问这块内存,MTE机制将检测到错误,并产生一个异常。
  2. 运行时监控和诊断:打标签的内存使得开发者可以追踪内存访问模式,识别内存是如何被程序的不同部分访问的。这在调试过程中尤为有用,因为它可以帮助发现那些隐蔽的内存错误。
  3. 保护关键数据:通过给敏感数据打个特定的Tag,你可以确保只有被授权的代码能够访问这些数据。如果其他不相关的代码尝试访问,标签不匹配会触发异常,这为敏感数据提供了一层额外的保护。
  4. 内存使用分析:Tag可以作为分析工具,以了解某类内存分配的分布和生命周期。例如,通过给特定类型的对象或资源分配统一的Tag,可以在运行时分析其分布情况。
  5. 内存泄露排查:如果一个内存块长时间没有释放,并且带有与之关联的Tag,那么这可能是一个内存泄露的迹象。分析这些留存的Tag可以帮助追踪潜在的内存泄露点。

进阶

Arm 撰写的 Android OS MTE 用户指南

GWP-ASan

GWP-ASan(GWP-ASan Will Provide Allocation SANity) 是一种原生内存分配器功能,可帮助查找释放后使用和堆缓冲区溢出 bug。

  1. GWP-ASan 不需要源代码或重新编译
  2. 适用于以 Android 11(API 级别 30)以上

概述

  1. GWP-ASan启用情况:在进程启动以及zygote派生时,系统会随机选择一些应用和平台可执行文件启用GWP-ASan。
  2. 作用:GWP-ASan旨在帮助开发者发现与内存相关的错误,并帮助应用准备好对ARM内存标记扩展(MTE)的支持。
  3. 内存分配拦截:一旦启用,GWP-ASan会随机拦截堆分配的子集,并将它们移入特殊区域,以发现通常难以检测的堆内存损坏错误。
  4. 低采样率的效果:即使是低采样率,只要用户基数足够大,也能够发现常规测试中未能发现的堆内存安全错误。
  5. 错误检测示例:GWP-ASan已在Chrome中发现大量错误。
  6. 信息收集:GWP-ASan为它拦截的所有分配收集额外信息,这些信息有助于内存安全违规的调试,且会被自动加入到原生代码的崩溃报告中。
  7. 性能影响:启用GWP-ASan后,会产生较小的CPU开销。
  8. 资源消耗:GWP-ASan会带来一定的固定RAM开销,目前累计每个受影响进程大约70KiB。

获取检测到“释放后堆使用”或“堆缓冲区溢出” bug

ActivityManager#getHistoricalProcessExitReasons json格式

[{"processName": "com.example.app","pid": 12345,"reason": "CRASH","timestamp": 1617998745000,"description": "NullPointer exception in MainActivity","trace": "java.lang.NullPointerException: Attempt to invoke virtual method on a null object reference\n\tat com.example.MainActivity.onCreate(MainActivity.java:85)\n\t...","importance": "FOREGROUND_SERVICE","status": "SIGNAL 9"},{"processName": "com.example.serviceapp","pid": 12346,"reason": "USER_REQUESTED","timestamp": 1617998746000,"description": "User requested force stop","trace": "","importance": "VISIBLE","status": "SIGNAL 9"},

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/783227.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微服务demo(三)nacosfeign

一、feign使用 1、集成方法 1.1、pom consumer添加依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>2.2.6.RELEASE</version></dependency&…

WEB APIS知识点案例总结

随机点名案例 业务分析: 点击开始按钮随机抽取数组中的一个数据,放到页面中点击结束按钮删除数组当前抽取的一个数据当抽取到最后一个数据的时候,两个按钮同时禁用(只剩最后一个数据不用抽了) 核心:利用定时器快速展示,停止定时器结束展示 <!DOCTYPE html> <html…

智慧公厕产品的特点、应用场景

随着城市化进程的加速和智能科技的不断发展&#xff0c;智慧公厕作为城市管理的重要组成部分&#xff0c;逐渐成为了现代城市的一道靓丽风景线。它的特点和应用场景备受人们关注和喜爱。 智慧公厕的特点有哪些呢&#xff1f;首先&#xff0c;它智能化的设备和感应技术为其特点…

华为昇腾认证考试内容有哪些

华为昇腾认证考试的内容主要包括理论知识和实践操作两部分。 在理论知识部分&#xff0c;考生需要掌握昇腾计算的基础知识&#xff0c;包括昇腾计算平台的架构、性能特点、应用场景等。此外&#xff0c;还需要深入理解昇腾AI框架、算子开发、模型优化等相关技术原理和应用方法…

《操作系统导论》第14章读书笔记:插叙:内存操作API

《操作系统导论》第14章读书笔记&#xff1a;插叙&#xff1a;内存操作API —— 杭州 2024-03-30 夜 文章目录 《操作系统导论》第14章读书笔记&#xff1a;插叙&#xff1a;内存操作API1.内存类型1.1.栈内存&#xff1a;它的申请和释放操作是编译器来隐式管理的&#xff0c;所…

Xcode删除原本的Git,再添加新的git

本文参考&#xff1a;Xcode怎么删除原本git,在重新设置新的git地址_ios xcode 删除原本git-CSDN博客 开发中会有一个问题。Xcode项目A 提交到Git服务器server1&#xff0c;此时项目A内部已经存在一个Git文件&#xff0c;与server1相关联。 此时你想将项目A提交到 另一个Git…

前端实现菜单搜索搜索(功能模版)

目录 前言正文 前言 总体界面如下所示&#xff1a; 正文 <template><div class"avue-searchs"click.self"handleEsc"><div class"avue-searchs__title">菜单搜索</div><div class"avue-searchs__content"…

PS从入门到精通视频各类教程整理全集,包含素材、作业等(4)复发

PS从入门到精通视频各类教程整理全集&#xff0c;包含素材、作业等 最新PS以及插件合集&#xff0c;可在我以往文章中找到 由于阿里云盘有分享次受限制和文件大小限制&#xff0c;今天先分享到这里&#xff0c;后续持续更新 PS人物数码照片处理技法视频教程 https://www.al…

Mybatis项目运行成功但是返回的数据是引用的地址

如图所示&#xff1a; 解决方法&#xff1a;是因为在实体类当中没有重写toString方法 成功输出&#xff1a;

企微获客助手到底有哪些价值?

获客助手作为企业微信官方提供的获客工具&#xff0c;在私域布局中确实展现了其强大的引流效率和便利性。这一工具通过简化传统引流过程中的复杂步骤&#xff0c;使得企业能够更高效地吸引和转化潜在客户。此外&#xff0c;获客助手还能实现不同渠道的无缝链接&#xff0c;进一…

脑机辅助推导算法

目录 一&#xff0c;背景 二&#xff0c;华容道中道 1&#xff0c;问题 2&#xff0c;告诉脑机如何编码一个正方形格子 3&#xff0c;让脑机汇总信息 4&#xff0c;观察图&#xff0c;得到启发式算法 5&#xff0c;根据启发式算法求出具体解 6&#xff0c;可视化 一&am…

C++ 项目:使用 GSL 数学运算库 C++ 调用Python

文章目录 Part.I IntroductionChap.I CMakeListsChap.II ExportLibGSL.hChap.III test_python.cpp Part.II GSL 使用方法Part.III C 调用 Python 使用方法相关博客 Part.I Introduction 本项目是一个使用 GSL 的小项目&#xff0c;还有 C 调用 Python。项目虽简单&#xff0c;…

【研发日记】Matlab/Simulink开箱报告(十一)——Requirements Toolbox

目录 前言 Requirements Toolbox 编写需求 需求联接设计 需求跟踪开发进度 追溯性矩阵 分析和应用 总结 前言 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;六&#xff09;——S-Fuction模块&#xff08;TLC&#xff09;》 见《开箱报告&#x…

挑战从0开始开发仿小红书app第一天

00后挑战从0开始开发仿小红书|Day01 前言 记录开发的全阶段&#xff0c;比如需求分析&#xff0c;开发过程&#xff0c;测试阶段。不懂代码没关系&#xff0c;可以看看互联网岗位在干嘛 会使用一些辅助编码工具&#xff0c;就是类似于ChatGPT的大模型&#xff0c;比如通义灵码…

java文件File和IO流(一)-- File文件,IO流,缓冲流,字节流,字符流

File文件操作类 java.io.File类&#xff1a;文件和文件目录路径的抽象表示形式&#xff0c;与平台无关 File 能新建、删除、重命名文件和目录&#xff0c;但File 不能访问文件内容本身。如果需要访问文件内容本身&#xff0c;则需要使用输入/输出流。 想要在Java程序中表示一个…

C语言数组详解

一维数组 创建和初始化 数组就是一组相同元素的集合。 他的创建&#xff1a; char arr[10]; int arr1[5]; 数组创建中 [] 里不能是变量&#xff0c;但是在c99标准之后就可以了被称为变长数组&#xff0c;但是不常用&#xff0c;而且变长数组不能初始化。 初始化&#xff…

[蓝桥杯 2016 国 C] 赢球票

[蓝桥杯 2016 国 C] 赢球票 题目描述 某机构举办球票大奖赛。获奖选手有机会赢得若干张球票。 主持人拿出 N N N 张卡片&#xff08;上面写着 1 ∼ N 1 \sim N 1∼N 的数字&#xff09;&#xff0c;打乱顺序&#xff0c;排成一个圆圈。 你可以从任意一张卡片开始顺时针数…

STM32的IAP技术,BootLoader

来源 三种下载方式&#xff1a; 1、ICP&#xff1a;ST-Link, 2、ISP: FlyMcu, 3、IAP IAP简介 IAP技术的核心在于BootLoader程序的设计&#xff0c;这段程序预先烧录在单片机中&#xff0c;正常的APP程序可以使用BootLoader程序中的IAP功能写入&#xff0c;也可以两部分代码一…

【React】vite + react 项目,进行配置 eslint

安装与配置 eslint 1 安装 eslint babel/eslint-parser2 初始化配置 eslint3 安装 vite-plugin-eslint4 配置 vite.config.js 文件5 修改 eslint 默认配置 1 安装 eslint babel/eslint-parser npm i -D eslint babel/eslint-parser2 初始化配置 eslint npx eslint --init相关…

【python】常用函数汇总(持续更新……)

文章目录 【numpy.exp()】返回e的幂次方&#xff0c;e是一个常数为2.71828【np.dot()】矩阵相乘【np.linalg.inv()】矩阵求逆 【numpy.exp()】返回e的幂次方&#xff0c;e是一个常数为2.71828 举例&#xff1a;numpy.exp() 【np.dot()】矩阵相乘 【要点】 1、前者的列数后者…