仪器显示内存泄漏 - Xcode 5 / iOS7

Posted

技术标签:

【中文标题】仪器显示内存泄漏 - Xcode 5 / iOS7【英文标题】:Instruments show memory leak - Xcode 5 / iOS7 【发布时间】:2013-09-26 13:46:33 【问题描述】:

我有以下代码:

NSString *bgImageName = [[Useful instance] getRootviewBackgroundImageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:bgImageName]];
imageView.clipsToBounds = YES;
CGRect rc = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[imageView setFrame:rc];
[self.view insertSubview:imageView atIndex:0];
[imageView release];

Instruments 在上述代码的第二行显示 100% 和内存泄漏,而在 xcode 4.6 中并非如此。我现在在 osx 10.8.5 上使用 xCode 5

看来,我正确释放了分配的 UIImageView(第 7 行),它在第 6 行插入到我的视图中,所以我看不出为什么仪器会发出内存泄漏警告。

有人知道为什么仪器会显示(在我看来)错误信息吗?

编辑:这是带有我的泄漏对象的分配摘要的仪器屏幕截图:

UIKit 和 QuartzCore 保留了我的对象,这就是我泄漏 UIImageView 的原因(或者我对这个假设有误?)。

UIImageView 被插入到我的 xib 文件中引用的视图(UIViewController)中。将我添加的UIImageView 添加到“self.view”后如何控制它会发生什么?

【问题讨论】:

什么对象被泄露了? “UIImageView”对象 我有类似的东西,我看到它只发生在模拟器 [imageview setImage:[UIImage imageNamed:@"img-568h@2x"]]; (在这里泄漏)我正在使用 arc xcode 5 ios 7 @dave 只有在针对 iOS 7 使用模拟器进行分析时才会出现泄漏。使用设备或模拟器针对所有 iOS 版本进行分析永远不会出现任何内存泄漏警告(请参阅 Dan Marinescu 的回答) ***.com/a/4304131/44964 【参考方案1】:

我在 iOS 7 上使用 Xcode 5 时遇到了同样的问题。经过一些实验后,我注意到 Instruments 在针对 iOS 6.1 模拟器或针对运行 iOS 7 的设备 (iPhone 5s) 运行时没有显示内存泄漏。基于这些我只能得出结论,这是一个误报,是 iOS 7 模拟器中的一个错误。

编辑:在我更新到 Xcode 5.0.1 和 OS X Mavericks 后,此问题不再发生(我猜这是第一个修复它但无法确定的问题)。

【讨论】:

我也想通了。现在将提交我的应用程序:) 感谢大家的帮助!【参考方案2】:

Instruments 显示了触发泄漏对象分配的代码行,以及不是对象实际泄漏的原因。打开引用计数跟踪并查看该图像视图上的所有保留/释放事件。会有额外的保留(或缺失的版本)。

【讨论】:

感谢您的帮助,但我仍然无法摆脱仪器中的泄漏对象。请看看我编辑的问题。【参考方案3】:

我注意到这发生在您的 RootViewController 实例上。这真的是***视图控制器(例如,您永远不会关闭/弹出的视图控制器)吗?如果是这样,则此分配摘要正确地告诉您图像视图仍然存在,并且奇怪的是它被报告为泄漏。

但是,如果视图控制器已被解除,那么您就有了真正的泄漏(尽管问题不在于您问题中的代码:您已经正确地做到了)。您的分配摘要证明您的UIImageView 永远不会被破坏。如果视图控制器被正确解除和释放,图像视图的分配摘要应该如下所示:

请注意,当我弹出视图控制器时(在我的 Profiling 会话中 28 秒),视图正在被释放,因此 UIImageView 也是如此(参见突出显示的两条线)。

您可以从分配摘要中得出两个结论:

UIImageView 上没有显示任何其他保留,这表明此图像视图根本不是问题。这不是您不小心在某处过度保留此图像视图的情况。

您看不到removeFromSuperview 的事实表明您的superview 本身永远不会被释放。

所以,问题是您的RootViewController 是否已从视图控制器层次结构中删除。如果是这样,那么你有一个泄漏或保留周期,可能是视图控制器本身,而不是这个图像视图。

顺便说一句,听起来你对这些话题已经很熟悉了,但我经常向人们介绍 WWDC 2012 视频iOS App Performance: Memory,它不仅描述了许多内存问题,还演示了使用 Instruments 来跟踪这些问题下降(例如显着的堆)。

【讨论】:

【参考方案4】:

我开始遇到同样的问题,我正在研究 imageNamed。我发现过去存在内存问题。我最终使用了 [[UIImage alloc] initWithContentsOfFile:actualPath] ,其中 actualPath 来自主包。

【讨论】:

【参考方案5】:

我认为@mishod 的答案是正确的。

我测试过,是的 UIImageView setImage 确实泄漏了!

如果你循环浏览一堆图片

   [yourImageView setImage:[UIImage imageNamed:@"sampleImage.png"]];

您可以看到仪器的内存使用量在增加。 从那以后,这似乎是某种缓存 循环浏览所有图像的内存使用量将持平。

正确的,或者至少是不泄漏的方法是:

   NSString *thePath = [[NSBundle mainBundle] pathForResource:@"sampleImage" ofType:@"png"];
   UIImage *newImage =  [[UIImage alloc] initWithContentsOfFile:thePath];
   [yourImageView setImage:newImage];

我在我的代码上验证了这一点,因为我的 APP 循环了很多次 大图像文件。

【讨论】:

【参考方案6】:

只是一个建议。不要在模拟器上运行 Instruments。在设备上进行。有很多差异,您会看到更好/相关的结果。例如。模拟器拥有比真实设备更多的内存。

【讨论】:

以上是关于仪器显示内存泄漏 - Xcode 5 / iOS7的主要内容,如果未能解决你的问题,请参考以下文章

仪器在 main.m (Xcode 4.3.1) 中显示泄漏

使用仪器检查 xcode 4 中的内存泄漏

如何解决 xcode(仪器)中的 iPhone 应用程序内存泄漏

一分钟后webview中的内存泄漏仅通过仪器

仪器报告内存泄漏。不明白为啥

内存泄漏仪器警告