【问题标题】:Releasing memory in iOS 5 under arc在 arc 下释放 iOS 5 中的内存
【发布时间】:2013-02-20 12:20:43
【问题描述】:

我知道这个问题问了很多次,但我还没有找到解决办法。我的应用程序按照 a->b->c->d->b 的顺序在视图之间移动。这意味着从视图“d”我并不总是返回,并且需要跳转到视图“b”。问题是视图“c”和“d”的内存没有释放,并且在一些循环之后(b->c->d->b->c....)应用程序崩溃了。操作的顺序非常重要。我不得不提到,我使用模态 segue 在视图之间导航。我尝试过多种方式释放内存:

  1. 放入 DidRecieveMemoryWarning:_myProperty = nil;
  2. 放入 ViewDidUnload:_myProperty = nil;
  3. 将所有属性更改为弱。
  4. 使用@autoreleasepool 包装代码。

没有任何帮助,应用一段时间后崩溃,如何通过“强制”释放视图和内存?

【问题讨论】:

  • 是什么让您确定崩溃与内存泄漏有关?
  • 用活动监视器检查它,总是在大约 420MB 时应用程序崩溃,不考虑查看它,并且我收到内存警告。
  • 当任何视图弹出导航堆栈时,如果您使用ARC,它将自动释放。您在问题中描述的情况永远不会发生,除非您以某种方式使对象保持活动状态,即指针存储在另一个数组中并保留它们等等......
  • 如果您确实收到内存警告:您如何应对它们,特别是:您会因此释放内存?

标签: ios xcode memory-leaks


【解决方案1】:

ARC 是为了不强制释放而让操作系统处理所有版本。您应该使用 xcode 工具 来了解您的应用使用了多少内存。在我看来,你的内存膨胀了,所以最好检查一下正在使用多少内存,以及你可以做些什么来优化它,这样分配容量就会保持在可接受的范围内。 (例如,在每个图像大小为 1Mb 的视图中加载 1000 张图像完全是浪费,并且可能会导致这种崩溃。这个例子是故意夸大的,所以你会明白的)

【讨论】:

  • 我已经打过很多次了,它太琐碎了我什至没有提到它,它与我的问题有什么关系?如果您想知道,我正在 iPad 2 上进行测试。在视图 b 上,我的应用程序使用大约 220MB,在 C 上使用 250MB,在 d 上使用 260MB,然后在 3-4 之后再次转到 b 并添加总内存至 320MB循环喜欢这个内存是 430MB 并且应用程序崩溃了。
  • 我需要在每个图像为 1Mb 的视图中加载“1000 张图像”,但我希望在退出视图后将其释放。你不帮我,你只是换个角度描述问题。
  • 我不是通灵者,我怎么知道你检查过了???我的回答确实给了你一个解释和一种可能的方法。而且您的问题表述得很糟糕,没有关于您如何初始化或利用您的视图的相关代码。不要指望别人猜你在做什么。
  • 您还应该检查其他应用程序是否正在运行并且可能会消耗内存以及导致设备上的高内存使用?您是否在应用中收到内存不足警告,或者您已经检查过这个 TRIVIAL 问题?
  • 在 ARC 中管理内存的不是操作系统,而是编译器。除了需要一些运行时支持的弱引用。
【解决方案2】:

Objective-C(主要)使用引用计数内存模型。有手动引用计数和自动引用计数(ARC)。

ARC 的工作原理

如果您曾经使用过手动引用计数并运行过 clang 静态分析器工具,您会发现它在查找内存泄漏方面做得非常出色。这就是 ARC 背后的想法——如果分析器能够很好地发现泄漏,那么为什么不让它执行内存管理呢?

因此,分析是在编译时完成的,生成的代码使用保留和释放调用进行检测。这是 ARC 的基础及其出色的内存模型,在性能和易用性之间取得了良好的平衡。它在移动计算中特别有用,因为与垃圾收集不同,它不需要任何额外的 CPU 周期或电池消耗。

(注意:ARC 还引入了弱引用,这是一种在运行时将 悬空指针 置空的方法)。

使用 ARC 并不像垃圾回收那么简单 - 您仍然需要了解引用计数内存模型的工作原理。可能会出现以下问题。

保留周期

内存泄漏的主要原因是保留周期。这就是对象 A 对对象 B 的引用,而对象 B 对对象 A 的引用。例如,AirlineFlight 包含一名乘客,而乘客有一个 AirlineFlight -> 内存泄漏。

这在 Cocoa 中很常见。另一个例子是一个 ViewController 拥有一个视图,而这个 View 有一个委托,也就是 ViewController。听起来有点熟?

为了避免保留循环,其中一个对象必须不保留另一个。最常见的方法是将一个指定为父级,另一个指定为子级。父母保留孩子,但孩子不保留父母。示例:

视图控制器

@interface MyViewController

@property (nonatomic, strong) MyView* view

@end

查看

@interface MyView

@property (nonatomic, assign) MyViewController* controller

@end

现在保留周期已被打破,内存泄漏将不再发生。

悬空指针

上面的例子不再有内存泄漏,但会导致另一个问题——悬空指针。视图控制器可能会消失,而视图仍然具有对控制器的引用。现在对控制器的任何调用都会导致崩溃。

有两种方法可以解决这个问题:

  1. 在 dealloc 方法中消除对控制器的引用。 . .但可能只是

  2. 使用弱引用,如下:

    @property (nonatomic, weak) MyViewController* controller
    

iOS 5 及更高版本(或 OSX 10.7)有一个小的运行时实用程序,可以跟踪悬空指针并为您消除它们 - 这些被称为弱引用。

查找内存泄漏

有几种方法。

  • 使用 clang 静态分析器检测保留周期。
  • 使用仪器工具
  • 我喜欢将日志语句放在我的控制器和其他关键类的 dealloc 方法中,以确保它们被释放。

寻找悬空指针

  • 使用环境变量 NS_ZOMBIES_ENABLED 编译(或在 Xcode 中编辑 Scheme 并单击复选框,它将为您设置此参数)。

自动释放池

另一个可能发生的问题是在一个运行循环中分配了太多的对象。 .要更正此问题,您可以在主池中创建另一个自动释放池。

@autoreleasepool
{

}

(在你的情况下,我认为这不是问题)。

【讨论】:

    【解决方案3】:

    我也遇到过这个问题,但我正在为 OSX10.8 而不是 iOS 编写可可应用程序。 我发现当我执行诸如显示新窗口然后一次又一次关闭之类的操作时,应用程序的内存使用量会一直增加。我每次看到的窗口似乎都是一个新窗口。 10MB->20MB->30MB... 最后,我直接双击了.app文件,再次查看了活动监视器。事实是它真的变得很正常。以发布模式运行的应用程序是相同的情况。所以我想如果你通过 Xcode Run 运行应用程序,ARC 不会在调试模式下立即释放内存。

    【讨论】:

      【解决方案4】:

      您是否使用过重的 png 图片?不久前我遇到了同样的问题,高度 x 宽度图像使用 RAM 的高度 x 宽度 x 4(因为它与 GPU 共享)。只有我的背景浪费了大约 120MB。如果是这种情况,请尝试重新调整图像尺寸。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-17
        • 1970-01-01
        • 2023-03-15
        • 1970-01-01
        • 2013-08-27
        • 1970-01-01
        • 2012-05-22
        相关资源
        最近更新 更多