HarmonyOS开发中,如何高效定位并分析内存泄露相关问题

HarmonyOS开发中,如何高效定位并分析内存泄露相关问题

  • (1)Allocation的应用
    • 调试方式
    • Memory泳道
    • Native Allocation泳道
  • (2)Snapshot
  • (3)ASan的应用
    • 使用约束
    • 配置参数
    • 使能ASan
      • 方式一
      • 方式二
    • 启用ASan
    • ASan检测异常码
  • (4)HWASan的应用
    • 功能介绍
    • 约束条件
    • 使能HWASan
      • 方式一
      • 方式二
    • 启用HWASan
  • 总结

应用在开发过程中,可能会因为API使用错误、变量未及时释放、异常频繁创建/释放内存等情况引发各种内存问题。
华为官方提供了多种方案来方便各位开发者分析解决内存相关问题,比如Allocation (获取native调用栈profiler)、SnapShot、ASan、HWASan,本文重点对这些工具的特点做些说明,同时结合实际案例对这些工具的应用做进一步讲解。

(1)Allocation的应用

Allocation是DevEco Studio 开发工具的 Profiler提供的内存场景分析工具,开发过程中可以使用Allocation来分析应用或服务在运行时的内存分配及使用情况,识别和定位内存泄漏、内存抖动以及内存溢出等问题,对应用或服务的内存使用进行优化。

调试方式

打开 DevEco Studio 找到 Profiler,DevEco Profiler提供Launch、ArkUI、Frame、Concurrency、ArkWeb、Network、Time、Allocation、Snapshot、CPU等场景化分析任务类型,在设备列表中选择设备(目前只支持真机),在进程列表中选择要调测的应用,选择Allocation并点击Create Session即可创建一次会话。右侧任务分析窗口可以选择Memory、Native Allocation具体分析。
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/7e0298bf884148d7b3facba13ac95332.png

Memory泳道

可以看到Memory泳道包含三个标识:PSS代表进程独占内存和按比例分配共享库占用内存之和,RSS是进程独占内存和相关共享库占用内存之和,USS代表进程独占内存。

在右边录制详情区域,工具控制栏上有很多小图标,鼠标放上去会有一些功能提示,可以添加一些录制选项,各泳道区域也有下拉框选项,下拉选择不同的设置可以调整录制功能。

单击任务窗口左上角的 ,启动录制,也可以选择左侧的任务列表中的,启动录制后,等待任务状态由“initializing”变为“recording”。录制过程中整个DevEco Profiler不能再点击其他的模板进行操作,如果想录制其他模板可以结束本次录制重新选择其他模板开始录制。
在这里插入图片描述
录制过程中,右侧任务分析窗口显示未recording状态,先要结束此次录制时,点击左侧Allocation按钮的stop按钮即可,结束录制之后可以看到当前session的各个不同内存类型对应的变化情况。
默认展示其中的五个子泳道,如要显示其他子泳道,可以点击主泳道的options标签并勾选其他泳道来查看。在这里插入图片描述
选择具体的子泳道可以在details模块看到不同的时间点,对应的内存值变化情况,方便开发者进一步定位问题。
在这里插入图片描述
特别提示:

  • 由于隐私安全政策,已上架应用市场的应用不支持录制此泳道。
  • 建议避免同时录制ArkTS Allocation及Native Allocation泳道,避免影响分析准确性。

Native Allocation泳道

Native Allocation泳道主要显示具体的Native内存分配情况,包括静态统计数据、分配栈、每层函数栈消耗的Native内存等信息。由于隐私安全政策,已上架应用市场的应用不支持录制此泳道。通过操作对应的options同样可以选择展示的类型,框选子泳道后显示具体的内存分配,包括静态统计数据、分配栈等。
在这里插入图片描述

如下图所示,为选中Native Allocation后的某种展示场景。

  • Statistics显示该段时间内的静态分配情况。包括分配方式(Malloc或Mmap)、总分配内存大小、总分配次数、尚未释放的内存大小、尚未释放次数、已释放的内存大小、已释放次数。
    点击任意对象上的跳转按钮,可跳转至此类对象的详细占用/分配信息。当前统计模式下不支持跳转。
  • Call Trees页签显示线程的内存分配栈情况。包括函数地址或符号、分配大小、占比以及函数栈帧的类别等。单击任一行栈帧,“More”区域将显示经过该栈帧的分配内存最大的调用栈。
  • Allocations List显示内存分配的详细信息。包括内存块起始地址、时间戳、当前活动状态、大小、调用的库、调用库的具体函数、事件类型(与Statistics页签的分配方式对应)等。

针对详情面板中所展示的函数栈帧信息(如下图所示),双击栈帧结点,工具便会在编辑器中打开相关源码文件,并定位到对应行号。此功能正常使用的前提是用于抓取性能数据的应用,是在DevEco Studio所在的开发环境中编译,且相关源文件位置并未改变。
在这里插入图片描述
值得注意的是,上图对应的category列表标识调用栈的类型,从语言层面分为ArkTS、NAPI以及Native,从归属层面分为开发者代码以及系统代码(如下图所示)。从这两个方面可以将调用栈类型归类如下:

  • ArkTS:程序正在执行ArkTS代码;
  • NAPI:程序正在运行的NAPI代码;
  • Native:程序正在执行的Native代码;其中每一个类型的亮色和灰色分别代表开发者和系统的代码。
    在这里插入图片描述

Native Allocation泳道的内存状态信息可以进一步过滤和筛选。选中Native Allocation后,details底部有两个默认过滤条件All Allocations、Native Size。

  • All Allocations(默认状态):详情区域展示当前框选时间段内的所有内存分配信息

  • Created & Existing:详情区域展示当前框选时间段内分配未释放的内存。

  • Created & Released:详情区域展示当前框选时间段内分配已释放的内存。
    在这里插入图片描述

  • Native Size:详情区域按照对象的原生内存进行展示。

  • Native Library:详情区域按照对象的so库进行展示。
    在这里插入图片描述

此外,在“Native Allocation”泳道的“Allocations List”页签中还可以通过so库名称进行筛选、搜索关键词筛选、内存分配堆栈进行筛选,此处不再做过多演示。

关于Allocation的更多介绍和使用方法可以在官方文档查看,基础内存分析:Allocation分析

(2)Snapshot

Snapshot是DevEco Profiler提供的一个内存快照分析工具,通过结合Memory实时占用情况,分析不同时刻的方舟虚拟机内存对象占用情况及差异,进而进行内存优化。

关于Snapshot具体的应用技巧可以借鉴官网Snapshot模板基本操作,或者借鉴使用Snapshot Insight分析ArkTS内存问题,本文不再赘述。

(3)ASan的应用

ASan(Address-Sanitizer)是内存检测的工具,用于发现内存飞踩第一现场,DevEco Studio为开发者集成了ASan能力,可以检测C/C++的地址越界问题,解决一些踩内存导致的异常crash的补充手段,对于一些明显不可能crash的场景可以尝试开启ASan。

使用约束

  • 如果应用内的任一模块使能ASan,那么entry模块需同时使能ASan。
  • 如果entry模块未使能ASan,该应用在启动时将闪退,出现CPP Crash报错。
  • ASan、TSan、HWASan不能同时开启,三个只能开启其中一个。

配置参数

ASAN_OPTIONS:在运行时配置ASan的行为,包括设置检测级别、输出格式、内存错误报告的详细程度等。ASAN_OPTIONS支持在app.json5中配置,也支持在Run/Debug Configurations中配置。app.json5的优先级较高,即两种方式都配置后,以app.json5中的配置为准。

以在app.json5中配置环境变量为例。打开AppScope > app.json5文件,添加配置示例如下。

{
  "app": {
    "appEnvironments": [
      {
        "name": "ASAN_OPTIONS",
        "value": "log_exe_name=true abort_on_error=0 print_cmdline=true" // 示例仅供参考,具体以实际为准
      },
    ],
    ...
  }
}

在Run/Debug Configurations中配置环境变量,具体可查看配置环境变量

使能ASan

可通过以下两种方式使能ASan。

方式一

  1. 在运行调试窗口(entry --> Edit Configurations),点击Diagnostics,勾选Address Sanitizer。
    在这里插入图片描述
    在这里插入图片描述
  2. 如果有引用本地library,需在library模块的build-profile.json5文件中,配置arguments字段值为“-DOHOS_ENABLE_ASAN=ON”,表示以ASan模式编译so文件。
    在这里插入图片描述

方式二

  1. 修改工程目录下AppScope/app.json5,添加ASan配置开关。
 "asanEnabled": true

在这里插入图片描述

  1. 设置模块级构建ASan插桩。
    在需要使能ASan的模块中,通过添加构建参数开启ASan检测插桩,在对应模块的模块级build-profile.json5中添加命令参数:
"arguments": "-DOHOS_ENABLE_ASAN=ON"

在这里插入图片描述

启用ASan

运行或调试当前应用。
当程序出现内存错误时,弹出ASan log信息,点击信息中的链接即可跳转至引起内存错误的代码处。

举例说明:
编写一段数组越界的C++代码,对外暴露接口,在ArkTs侧调用该方法。
在这里插入图片描述

Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(() => {
            hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3));
            hilog.info(0x0000, 'testTag', 'HeapBufferOverflow() ', testNapi.HeapBufferOverflow());
            // this.memoryLeak()
          })

运行当前项目,触发Button的onClick事件调用之后,应用崩溃,弹出FaultLog信息。
在这里插入图片描述
点击 Jump to Log跳转到FaultLog模块。
在这里插入图片描述

可以看到log信息有明确的log信息,报错原因为“AddressSanitizer: heap-buffer-overflow”,同样的还有多个链接地址。“appspawn30149==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x005b7fe7153b at pc 0x007c24fc309c bp 0x007eba84b160 sp 0x007eba84b158
”可以直接跳转到官网关于“heap-buffer-overflow”的报错解释以及解决方案。另外多个包含“/data/storage/el1/…”的地址能精确定位到C/C++层代码出错的具体位置。
在这里插入图片描述
然后我们就发现这是数组越界造成的,所以解决方案就是“对于已知大小的集合,注意访问不要越界,位置大小的集合访问前先判断大小。”

ASan检测异常码

ASan不仅能检测出“heap-buffer-overflow”异常,还能检测很多其他类型的内存异常,关于这些异常问题及解决方案,如下所示。

  • heap-buffer-overflow

    • 背景/原理:访问越界。
    • 影响/报错:导致程序存在安全漏洞,并有崩溃风险。
      开启ASan检测后,触发demo中的函数,应用闪退报ASan,包含字段:AddressSanitizer:heap-buffer-overflow
    • 修改方法:注意数组容量不要访问越界。
    • 推荐建议:已知大小的集合注意访问不要越界,位置大小的集合访问前先判断大小。
  • stack-buffer-underflow

    • 背景/原理:访问越下界。
    • 影响/报错:导致程序存在安全漏洞,并有崩溃风险。
      开启ASan检测后,触发demo中的函数,应用闪退报ASan,包含字段:AddressSanitizer:stack-buffer-underflow
    • 修改方法:访问索引不应小于下界。
    • 推荐建议:访问索引不应小于下界。
  • stack-use-after-scope

    • 背景/原理:栈变量在作用域之外被使用。
    • 影响/报错:导致程序存在安全漏洞,并有崩溃风险。
      开启ASan检测后,触发demo中的函数,应用闪退报ASan,包含字段:AddressSanitizer:stack-use-after-scope
    • 修改方法:在作用域内使用该变量。
    • 推荐建议:注意变量作用域。
  • attempt-free-nonallocated-memory

    • 背景/原理:尝试释放了非堆对象(non-heap object)或未分配内存。
    • 影响/报错:导致程序存在安全漏洞,并有崩溃风险。
      开启ASan检测后,触发demo中的函数,应用闪退报ASan,包含字段:
      AddressSanitizer: attempting free on address which was not malloc()-ed
    • 修改方法:不要对非堆对象或未分配的内存使用free函数。
    • 推荐建议:不要对非堆对象或未分配的内存使用free函数。
  • double-free

    • 背景/原理:重复释放内存。
    • 影响/报错:导致程序存在安全漏洞,并有崩溃风险。
      开启ASan检测后,触发demo中的函数,应用闪退报ASan,包含字段:
      AddressSanitizer: double-free
    • 修改方法:已经释放一次的指针,不要再重复释放。
    • 推荐建议:变量定义声明时初始化为NULL,释放内存后也应立即将变量重置为NULL,这样每次释放之前都可以通过判断变量是否为NULL来判断是否可以释放。
  • heap-use-after-free

    • 背景/原理:当指针指向的内存被释放后,仍然通过该指针访问已经被释放的内存,就会触发heap-use-after-free。
    • 影响/报错:导致程序存在安全漏洞,并有崩溃风险。
      开启ASan检测后,触发demo中的函数,应用闪退报ASan,包含字段:
      AddressSanitizer: heap-use-after-free
    • 修改方法:已经释放的指针不要再使用,将指针设置为NULL/nullptr。
    • 推荐建议:实现一个free()的替代版本或者 delete析构器来保证指针的重置。
  • Other categories
    未知的错误类型,持续更新中。

(4)HWASan的应用

HWASan(Hardware-Assisted Address Sanitizer)是一款类似于ASan的内存错误检测工具,目前仅适用于。 与ASan相比,HWASan使用的内存减少很多,因而更适合用于整个系统的清理。

功能介绍

与ASan相比,HWASan具有如下特征:

  • CPU开销约为2倍。
  • 代码大小开销为40% - 50%。
  • RAM开销为10% - 35%。

HWASan能检测到ASan所能检测到的同一系列错误:

  • 堆栈和堆缓冲区上溢/下溢。
  • 释放之后的堆使用情况。
  • 重复释放/错误释放。

和ASan相比,HWASan具有以下优点:

  • HWASan不需要安全区来检测buffer overflow,既极大地降低了工具对于内存的消耗,也不会出现ASan中某些overflow检测不到的情况。
  • HWASan不需要隔离区来检测UseAfterFree,因此不会出现ASan中某些UseAfterFree检测不到的情况。
  • 此外,HWASan还可以检测返回之后的堆栈使用情况。

约束条件

  • HWASan检测仅适用于AArch64架构的硬件。
  • ASan、TSan、HWASan不能同时开启,三个只能开启其中一个。

使能HWASan

方式一

在运行调试窗口(例如entry --> Edit Configurations),点击Diagnostics,勾选Hardware-Assisted Address Sanitizer开启检测。

在这里插入图片描述

方式二

修改工程目录下的AppScope/app.json5文件,添加HWASan配置开关。

"hwasanEnabled": true

在这里插入图片描述
在需要使能HWASan的模块中,通过添加构建参数开启HWASan检测插桩,在对应模块的模块级build-profile.json5中添加命令参数:

"arguments": "-DOHOS_ENABLE_HWASAN=ON"

在这里插入图片描述

启用HWASan

运行或调试当前应用。当程序出现内存错误时,弹出HWASan log信息,点击信息中的链接即可跳转至引起内存错误的代码处。

关于HWAan的代码实例和应用场景基本和ASan一致,此处就不做重复是说明了。

总结

  • 根据Allocation分析的结果,可以方便开发者优化应用的服务和组件的内存使用。例如,减少不必要的内存分配和释放,优化数据结构的使用等。

  • 通过ASan或HWASan分析问题时,精准定位内存出错原因和具体位置,开发者应修复这些内存管理的问题,如确保所有分配的内存都被正确释放。

  • 开发过程中,使用合适的内存管理和回收机制 :确保应用在不需要内存资源时能够有效地回收和管理这些资源,避免过度使用内存。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Python】Selenium模拟在输入框里,一个字一个字地输入文字

我们平常在使用Selenium模拟键盘输入内容,常用的是用send_keys来在输入框上输入字: 基本的输入方式: input_element driver.find_element(By.ID, searchBox) input_element.send_keys("我也爱你") #给骚骚的自己发个骚话不过这种…

泷羽sec学习打卡-shell命令6

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都 与本人无关,切莫逾越法律红线,否则后果自负 关于shell的那些事儿-shell6 if条件判断for循环-1for循环-2实践是检验真理的唯一标准 if条件判断 创建…

【ArkTS】使用AVRecorder录制音频 --内附录音机开发详细代码

系列文章目录 【ArkTS】关于ForEach的第三个参数键值 【ArkTS】“一篇带你读懂ForEach和LazyForEach” 【小白拓展】 【ArkTS】“一篇带你掌握TaskPool与Worker两种多线程并发方案” 【ArkTS】 一篇带你掌握“语音转文字技术” --内附详细代码 【ArkTS】技能提高–“用户授权”…

数据分析案例-笔记本电脑价格数据可视化分析

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

系统监控——分布式链路追踪系统

摘要 本文深入探讨了分布式链路追踪系统的必要性与实施细节。随着软件架构的复杂化,传统的日志分析方法已不足以应对问题定位的需求。文章首先解释了链路追踪的基本概念,如Trace和Span,并讨论了其基本原理。接着,文章介绍了SkyWa…

游戏引擎学习第25天

Git: https://gitee.com/mrxiao_com/2d_game 今天的计划 总结和复述: 这段时间的工作已经接近尾声,虽然每次编程的时间只有一个小时,但每一天的进展都带来不少收获。尽管看起来似乎花费了很多时间,实际上这些日积月累的时间并未…

GaussDB TPOPS 搭建流程记录

目录 前言 环境准备 安装前准备 安装TPOPS 总结 前言 由于工作需要,准备将现有Oracle数据切换至GaussDB数据库。在这里记录一下安装GaussDB数据库过程踩的坑。 首先,我装的是线下版本,需要先装一个GaussDB轻量化管理平台(…

Web网页设计作业成品源码分享(持续更新)

🎉Web前端大作业专栏推荐 📚Web前端期末大作业源码分享 ✍️html网页设计、web前后端网站制作、大学生网页设计作业、个人网站制作、jQuery网站设计、uniapp小程序、vue网站设计、node.js网站设计、网页成品模板、期末大作业,各种设计应有尽有…

facebook欧洲户开户条件有哪些又有何优势?

在当今数字营销时代,Facebook广告已成为企业推广产品和服务的重要渠道。而为了更好地利用这一平台,广告主们需要理解不同类型的Facebook广告账户。Facebook广告账户根据其属性可分为多种类型,包括个人广告账户、企业管理(BM&#…

Qt 2D绘图之三:绘制文字、路径、图像、复合模式

参考文章链接: Qt 2D绘图之三:绘制文字、路径、图像、复合模式 绘制文字 除了绘制图形以外,还可以使用QPainter::darwText()函数来绘制文字,也可以使用QPainter::setFont()设置文字所使用的字体,使用QPainter::fontInfo()函数可以获取字体的信息,它返回QFontInfo类对象…

一种多功能调试工具设计方案开源

一种多功能调试工具设计方案开源 设计初衷设计方案具体实现HUB芯片采用沁恒微CH339W。TF卡功能网口功能SPI功能IIC功能JTAG功能下行USB接口 安路FPGA烧录器功能Xilinx FPGA烧录器功能Jlink OB功能串口功能RS232串口RS485和RS422串口自适应接口 CAN功能烧录器功能 目前进度后续计…

【C++】深入优化计算题目分析与实现

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯第一题:圆的计算我的代码实现代码分析改进建议改进代码 老师的代码实现代码分析可以改进的地方改进代码 💯第二题:对齐输出我的代码实现…

动手学深度学习10.5. 多头注意力-笔记练习(PyTorch)

本节课程地址:多头注意力代码_哔哩哔哩_bilibili 本节教材地址:10.5. 多头注意力 — 动手学深度学习 2.0.0 documentation 本节开源代码:...>d2l-zh>pytorch>chapter_multilayer-perceptrons>multihead-attention.ipynb 多头注…

大R玩家流失预测在休闲社交游戏中的应用

摘要 预测玩家何时会离开游戏为延长玩家生命周期和增加收入贡献创造了独特的机会。玩家可以被激励留下来,战略性地与公司组合中的其他游戏交叉链接,或者作为最后的手段,通过游戏内广告传递给其他公司。本文重点预测休闲社交游戏中高价值玩家…

软件质量保证——单元测试之白盒技术

笔记内容及图片整理自XJTUSE “软件质量保证” 课程ppt,仅供学习交流使用,谢谢。 程序图 程序图定义 程序图P(V,E),V是节点的集合(节点是程序中的语句或语句片段),E是有向边的集合…

Node.js:开发和生产之间的区别

Node.js 中的开发和生产没有区别,即,你无需应用任何特定设置即可使 Node.js 在生产配置中工作。但是,npm 注册表中的一些库会识别使用 NODE_ENV 变量并将其默认为 development 设置。始终在设置了 NODE_ENVproduction 的情况下运行 Node.js。…

Zookeeper的通知机制是什么?

大家好,我是锋哥。今天分享关于【Zookeeper的通知机制是什么?】面试题。希望对大家有帮助; Zookeeper的通知机制是什么? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper的通知机制主要通过Watcher实现,它是Zookeeper客…

Request method ‘POST‘ not supported(500)

前端路径检查 查看前端的请求路径地址、请求类型、方法名是否正确,结果没问题 后端服务检查 查看后端的传参uri、传参类型、方法名,结果没问题 nacos服务名检查 检查注册的服务是否对应(我这里是后端的服务名是‘ydlh-gatway’,服务列表走…

ESP32-S3模组上跑通ES8388(13)

接前一篇文章:ESP32-S3模组上跑通ES8388(12) 二、利用ESP-ADF操作ES8388 2. 详细解析 上一回解析了es8388_init函数中的第6段代码,本回继续往下解析。为了便于理解和回顾,再次贴出es8388_init函数源码,在…

Ubuntu 包管理

APT&dpkg 查看已安装包 查看所有已经安装的包 dpkg -l 查找包 apt search <package_name>搜索软件包列表&#xff0c;找到与搜索关键字匹配的包 dpkg与grep结合查找特定的包 dpkg -s <package>&#xff1a;查看某个安装包的详细信息 安装包 apt安装命令 更新…