如何排查内存泄漏

本文详细介绍如何使用Chrome的多种工具进行内存调试,包括任务管理器、DevTools的Performance面板、Memory面板等,涵盖内存占用、JS堆分析、堆快照对比、内存分配时间轴等高级技巧,帮助开发者有效定位和解决内存泄漏问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

工具:

  1. Chrome[kroʊm]任务管理器

    用来粗略地查看内存使用情况。

    入口在右上角三个点 -> 更多工具 -> 任务管理器,然后右键表头 -> 勾选JS使用的内存,主要关注两列:

    1. 内存占用空间。表示原生内存,DOM节点存储在原生内存中,如果此值正在增大,则说明正在创建DOM节点;
    2. JS使用的内存。表示JS堆,此列包含两个值,需要关注的是实时值(括号中的数值)。实时数值表示页面上的可访问对象正在使用的内存量。如果该数值在增大,要么是正在创建新对象,要么是现有对象正在增长。

    在这里插入图片描述

  2. Chrome DevTools Performance面板

    用来观察内存变化趋势。

    入口在DevTools的Performance面板,然后勾选Memory,如果想看页面首次加载过程内存使用情况的话,Command + R刷新页面,会自动记录整个加载过程。想看某些操作前后的内存变化的话,操作前点“黑点”按钮开始记录,操作完毕点“红点”按钮结束记录。

    记录完毕后勾选中部的JS Heap,蓝色折线表示内存变化趋势,如果总体趋势不断上涨,没有大幅回落,就再通过手动GC来确认:再操作记录一遍,操作结束前或者过程中做几次手动GC(点“黑色垃圾桶”按钮),如果GC的时间点折线没有大幅回落,整体趋势还是不断上涨,就有可能存在内存泄漏。

    或者更粗暴的确认方式,开始记录 -> 重复操作50次 -> 看有没有自动GC引发的大幅下降,在使用的内存大小达到阈值时会自动GC,如果有泄漏的话,操作n次总会达到阈值,也可以用来确认内存泄漏问题是否已修复。

    PS:还能看到document数量(可能针对iframe),节点数量、事件监听器数量、占用GPU内存的变化趋势,其中节点数量及事件监听器数量变化也有指导意义。
    在这里插入图片描述

  3. Chrome DevTools Memory面板
    在这里插入图片描述
    这个面板有3个工具,分别是堆快照、内存分配情况和内存分配时间轴:

    1. 内存分配时间轴(Record Allocation Timeline),用来查看实时的内存分配及回收情况。

      点开时间轴,对页面进行各种交互操作,出现的蓝色柱子表示新内存分配,灰色的表示释放回收,如果时间轴上存在规律性的蓝色柱子,那就有很大可能存在内存泄漏。

      然后再反复操作观察,看是什么操作导致蓝色柱子残留,剥离出具体的某个操作。
      在这里插入图片描述

    2. 堆快照(Take Heap Snapshot),用来具体分析各类型对象存活情况,包括实例数量、引用路径等等;

      堆快照用来进一步分析,找到泄漏的具体对象类型。

      到这里应该已经锁定可疑的操作了,通过不断重复该操作,观察堆快照各项的数量变化来定位泄漏对象类型。

      堆快照有4种查看模式:

      Summary:摘要视图,展开并选中子项查看Object’s retaining tree(引用路径);

      Comparison:对比视图,与其它快照对比,看增、删、Delta数量及内存大小;

      Containment:俯瞰视图,自顶向下看堆的情况,根节点包括window对象,GC root,原生对象等等;

      Dominators:支配树视图,新版Chrome好像去掉了,展示之前术语概念部分提到的支配树。

      其中最常用的是对比视图和摘要视图,对比视图可以把2次操作和1次操作的快照做diff,看Delta增量,找出哪类对象一直在增长。摘要视图用来分析这类可疑对象,看Distance,找出奇怪的长路径上,哪一环忘记断开了。

      看摘要视图有个小常识是新增的东西是黄底黑字,删除的是红底黑字,本来就有的是白底黑字,这一点很关键。
      在这里插入图片描述

    3. 内存分配情况(Record Allocation Profile),用来查看分配给各函数的内存大小;
      在这里插入图片描述

其中内存分配时间轴和堆快照比较有用,时间轴用来定位内存泄漏操作,对快照用来具体分析问题。

在FreeRTOS (Real-Time Operating System) 中排查内存泄露通常涉及以下几个步骤: 1. **检查分配和释放**:确保你在创建任务、堆栈或静态内存块时,都对应地进行了正确的`xPortMalloc()` 和 `vPortFree()` 或者`pdHeapCreate()`、`pdHeapDelete()`等函数的调用。如果没有正确释放资源,可能会导致内存泄漏。 2. **避免野指针**:确保在完成对某个内存区域的操作后,将指向该区域的指针设为NULL,防止误操作再次访问已释放的内存。 3. **定期分析内存使用**:使用FreeRTOS提供的内存分析工具或者第三方工具,如`xtensa_trace_buf`,可以记录程序运行过程中的内存状态,帮助发现异常增长。 4. **审查任务和队列管理**:检查是否有未销毁的任务或阻塞的队列,这些可能导致内存占用不断增加。 5. **代码审查**:仔细检查所有的内存分配和释放代码,特别是那些可能导致内存泄漏的复杂逻辑部分。 6. **限制堆大小**:设置合理的heap区大小,并监控是否超过预设值,超出则可能是内存泄露的一个提示。 7. **使用静态代码分析工具**:有些工具如PVS-Studio等可以帮助检测C/C++代码中的潜在内存问题。 8. **单元测试和集成测试**:编写测试用例验证内存管理操作的有效性,尤其是涉及到动态内存的部分。 如果你怀疑有内存泄露,应密切关注系统的内存使用情况,如果系统资源持续消耗而无明显释放迹象,就需要进一步追踪和定位问题了。记住,排查这类问题需要耐心和细心,逐步排除可能的源头。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值