4

我正在使用 ARC,应用程序崩溃说收到内存警告。我用过苹果仪器:

http://tinypic.com/view.php?pic=21kedxt&s=5

看起来我没有任何泄漏,但我找不到哪里出错了。崩溃与内存和到期弧有关,我不能使用释放和任何类型。这是我第一次使用 arc 处理内存使用情况。有没有我可以调试这个,因为我已经处理了将近两个月。我的代码在我的 git 集线器上,所以如果你看一下它会很有帮助。你可以在这里找到它。

我正在处理这个问题好几个星期,并想结束这个问题。谢谢。

4

3 回答 3

6

并非所有“泄漏”都显示在 Instruments 的“泄漏”工具中。而且,值得注意的是,如果视图控制器具有强引用循环,则不仅视图控制器不会被释放,而且它的任何成员都不会被释放。但是看看你的分配,你的内存永远不会被释放,所以你可能确实在某个地方有泄漏。但是,我们很难诊断,因为您的 github 项目不完整。但这里有一些想法:

  1. 强参考周期并不总是出现在泄漏工具中。

  2. 在传统的强引用循环的一个变体中,您的代码使用重复NSTimer,这将保持对您的视图控制器的强引用,这将导致您的视图控制器永远不会被释放(因为计时器保持其对您的视图控制器的强引用)。要解决此问题,您的视图控制器必须在关联视图消失时停止计时器:

    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
    
        self.timer = [NSTimer scheduledTimerWithTimeInterval: 0.05f target: self selector: @selector(tick) userInfo: nil repeats: YES];
    }
    
    - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
    
        [self.timer invalidate];
        self.timer = nil;
    }
    
  3. 除了像上面这样的强引用循环之外,另一个可能导致分配增加的现象,就像您与我们分享的那样,是视图控制器之间的循环流。例如,如果您的应用程序执行从视图控制器 A 到视图控制器 B 的推送/模态 segue,则应用程序必须弹出/关闭/展开回到视图控制器 A。如果您从 B 推送/模态到 A 的新实例,您最终会放弃 A 的旧实例,从而产生像您这样的分配图。

这些只是可能导致分配图的一些示例。但是我们很难通过提供的有限信息来进一步诊断。

在做任何其他事情之前,请使用 Xcode 的静态分析器( “产品”菜单上的command++或“分析” shiftB,并确保您在那里获得一份干净的健康清单。让 Xcode 帮助您识别代码中的编程问题。

一旦您解决了静态分析器发现的任何问题,您就可以深入了解 Instruments。请参阅 WWDC 2012 视频,iOS 应用性能:内存。大约 32 分钟后,它显示了一个与您的非常相似的分配图,描述了这些问题的三个来源(泄漏、废弃内存或缓存内存),并向您展示了如何使用分配工具来确定准确的来源问题。

您应该观看该视频,您肯定会熟悉分配工具功能(例如比较堆快照)以识别泄漏的对象,或查看扩展详细信息并调用树以查找创建泄漏对象的源代码. 一旦您准确地确定了泄漏的内容,我们就可以帮助您解决问题。


顺便说一句,甚至比该视频中描述的大头图更容易,我经常只需option单击并拖动“分配”图表中的特定尖峰(特别是显然从未释放过的尖峰)。如果您这样做,对象摘要将向您显示在该执行窗口期间已分配但未释放的对象(如果您按“实时字节”排序,则最有用):

对象摘要

这可能会有所帮助,但有时它只是神秘的CFStringCGImage分配的。因此,查看这些对象在代码中的分配位置有时很有用。如果您从“统计”-“对象摘要”切换到“调用树”,它现在将显示您的每个方法占用了多少内存(如果我还选中“反转调用树”,我发现这个屏幕最有用”和“隐藏系统库”):

调用树

如果您在此处双击符号名称,它实际上会向您显示有问题的代码:

代码示例

通过这个过程,我可以看到在那个尖峰处分配了什么,我现在可以确定为什么那个内存永远不会被释放(在这种情况下,这是我故意使用的重复计时器,但我从来没有invalidated)。

还有其他技巧在更复杂的场景中很有用(我特别喜欢让我的代码信号标志出现在仪器中,这样我就可以更准确地将我的代码中的活动与仪器中发生的事情相关联),但这可能太多了进入这里。希望optionInstruments 中的这种单击并拖动将成为一个有用的工具,用于识别正在分配和从未释放的内容。

于 2013-09-06T17:35:25.373 回答
0

我看了你在 github 上的代码

  1. 有一个文件名 iCarousel.m。确保它与 ARC 兼容,如果不兼容,则转到目标/构建阶段/编译源并fno-objc-arc为 iCarousel.m 提供标志。

  2. 在所有类的 viewdidunload 方法中使所有对象为零。

希望它会帮助你。

于 2013-09-02T10:32:01.807 回答
0
  1. 在某些情况下,ARC 不起作用(我的意思是按设计)。当你使用 CoreFoundation 或任何低于 Cocoa 级别的东西时,你需要像以前一样管理你的内存。此外,您可能有保留周期(最常见的是块)。尝试分析项目(在 Xcode 中构建旁边)或使用 Instruments 运行
  2. 如果您只是使用大量内存,ARC 将无济于事。您的数据集可能太大,您需要重构以在给定时间使用更少的内存
于 2013-09-02T09:59:44.683 回答