【问题标题】:How to fix memory leaks in iOS applications?如何修复 iOS 应用程序中的内存泄漏?
【发布时间】:2020-05-25 17:55:21
【问题描述】:

我在运行我的应用程序时发现很少有内存泄漏。供您参考,我将分享 Instrument 调试日志的屏幕截图以及 Xcode Debugg 内存图工具。我不明白这里出了什么问题。请帮我解决内存泄漏。

请帮助我修复图像中的记忆显示。谢谢。

【问题讨论】:

  • 通过点击红色图标,您将能够回溯并识别泄漏。
  • 点击红色图标后,泄露的对象显示为带有字节的malloc。我不知道问题发生在哪里以及如何解决它。
  • 你能在这里分享一个这样的屏幕吗?或者,您也可以直接在 XCode 中检查内存图。您只需在通过 XCode 运行应用程序时,点击 Xcode 调试栏中的内存调试按钮即可。
  • 我也分享了内存图。请点击内存调试器图表。
  • XTubeManager 和 GlueTubeNanager 是什么?那些是你的吗?如果是这样,那就从属于你的大物件开始吧。

标签: swift xcode memory-leaks xcode-instruments


【解决方案1】:

我知道这是一个老问题,但有几点意见。

  1. 当您有很多正在泄漏的对象时,请关注高级对象(尤其是您自己的类)。我们不在乎为什么数组没有被释放。我们关心为什么没有发布强烈引用它的项目。 XTubeManagerGlueTubeManager 可能是开始搜索的好地方,但我不知道左侧面板中还有哪些高级对象。

  2. 当您有泄漏时,使用“Malloc Stack Logging”功能非常有用。所以编辑你的方案(command+;或“产品”»“方案”»“编辑”)并转到“诊断”部分并暂时打开“Malloc”堆栈日志”:

    然后,当您选择一个泄漏的对象时,您可以使用右侧的内存检查器面板查看它的实例化位置:

    在堆栈跟踪中查找白色条目(您的代码),而不是所有灰色的系统项。当您将项目悬停在该堆栈跟踪中时,甚至还有一个小箭头可以让您跳转到有问题的代码。在我的示例中,泄漏的对象在 viewDidLoad 中实例化。

    这不会告诉您泄漏的原因,但您将能够看到相关对象在代码中的实例化位置,并且您可以从那里开始调查,诊断为什么在代码中的该点创建对象仍然有挥之不去的强烈参考。

    请记住在完成诊断后关闭“Malloc Stack Logging”功能。


顺便说一句,当我们看到URLSession 对象没有被释放时,这就引出了一个问题,即您是否实例化了URLSession 对象(而不是使用shared 实例)并且忽略了调用finishTasksAndInvalidate。理想情况下,您应该有一个 URLSession 并将其重用于所有网络活动(或使用 shared 实例),但如果您必须实例化会话,请确保在完成后使它们无效。

【讨论】:

    【解决方案2】:

    您不需要使用 Instruments。那是老办法。使用 Xcode 本身。

    Visual Debugging with Xcode - 24:45

    观看视频是必须的,但视频的摘要是这样的:

    有两种类型的内存问题。您只需在应用程序中重复 2-3 次流程即可确定内存图已捕获它

    • 泄漏。 Xcode 将用紫色图标对此进行注释。可能的有:委托、闭包
    • 被遗弃的内存。 Xcode 不会对此进行注释。但它仍然会增加你的内存占用。可能的示例有:一个永不失效的重复计时器、NotificationCenter、一个永不结束的 DispatchWorkItem

    对于泄漏,内存图是一个循环,即两种方式。

    对于废弃的内存,图表不是两种方式。它只是一个被 Apple 归类为“根路径”的对象,它引用您的对象并且永不放手。有关更多信息,请参阅here

    【讨论】:

      【解决方案3】:

      在这种情况下,仅仅因为某些工具说你有内存泄漏并不意味着你有一个。数据量似乎不到1MB,没什么。您的工具怀疑存在泄漏,因为数据已分配但未释放,但这些是单个对象。内存很可能会在以后被释放或重用。

      使用您的软件数小时并检查内存使用量是否变大。

      【讨论】:

        【解决方案4】:

        移动设备上的内存是一种共享资源。对其进行不当管理的应用程序会出现内存不足、崩溃和性能大幅下降的问题。 所以要修复它,请按照以下步骤操作 打开 Xcode 并构建以进行分析。 发射仪器。 使用该应用程序,尝试重现尽可能多的场景和行为。 注意泄漏/内存峰值。 寻找内存泄漏的来源。 解决问题。

        【讨论】:

          【解决方案5】:

          在您的内存调试器图中,您必须确定哪些类相互引用,例如:

          Entry Controller Home Controller Feed Controller Entry Controller Home Controller

          你能看到上面的代码是如何在主控制器和入口控制器之间循环的吗?

          您必须确定哪个是weak 引用,哪个是强引用,换句话说,哪个保留在内存中,哪个应该放开。

          希望这会有所帮助。如果您需要进一步说明,请随时发表评论。

          【讨论】:

            猜你喜欢
            • 2017-06-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-06-16
            • 2021-01-11
            • 1970-01-01
            • 2022-08-05
            • 1970-01-01
            相关资源
            最近更新 更多