Iphone 内存泄漏工具告诉我零泄漏,但内存占用不断增加

Iphone 内存泄漏工具告诉我零泄漏,但内存占用不断增加,iphone,xcode,memory,Iphone,Xcode,Memory,我正在SDK 3.2中运行我的应用程序的一些内存评测,我使用“泄漏”评测器查找我的所有内存泄漏,并将它们全部堵塞。这是一个scrollView navigationController应用程序,其中有瓷砖,你点击一个瓷砖,它会进入一个新的瓷砖视图,等等,我可以深入到很多层次,一直回到顶部,“泄漏”探查器说一切都很酷 然而,如果我在“ObjectAlloc”探查器中观察内存占用,内存占用会随着我的深入而不断增加(这似乎是合理的),但当我退出视图时,内存占用不会像我预期的那样下降 我知道这是一个模糊

我正在SDK 3.2中运行我的应用程序的一些内存评测,我使用“泄漏”评测器查找我的所有内存泄漏,并将它们全部堵塞。这是一个scrollView navigationController应用程序,其中有瓷砖,你点击一个瓷砖,它会进入一个新的瓷砖视图,等等,我可以深入到很多层次,一直回到顶部,“泄漏”探查器说一切都很酷

然而,如果我在“ObjectAlloc”探查器中观察内存占用,内存占用会随着我的深入而不断增加(这似乎是合理的),但当我退出视图时,内存占用不会像我预期的那样下降

我知道这是一个模糊的应用程序描述,但我不能准确地发布一行代码:)还应该注意的是,我正在使用coreData来存储图像数据,所以随着选择的节点越来越多,数据库的大小也越来越大,不知道是否/何时从内存中释放


给出了什么?

根据在核心数据中构建对象图的方式,它的内存使用量可能会意外地增长

一个常见的错误是将对象存储在复杂且经常出错(加载到内存中)的实体中。这会导致每当引用实体的任何其他部分时,大blob都会加载/保留在内存中。随着对象图的增长,它会消耗越来越多的内存,除非您主动删除对象然后保存该图

例如:您有一个人实体,其中包含大量文本信息,例如姓名、地址等,以及一张大照片。如果您将照片设置为人物实体的属性,则只要人物实体出现故障,照片就会出现在内存中。如果您获得属性名,那么photo属性也会在内存中


为了避免这种情况,blob应该位于自己的实体中,然后链接到关系中的其他实体。由于关系对象在直接调用之前不会出现故障,因此在需要之前,它们可能会一直处于内存不足状态

您可以拥有一个不断增长的程序,而不必泄漏内存。假设您从输入中读取单词,并将它们存储在链接列表中动态分配的内存块中。当你读到更多的单词时,列表会不断增加,但是所有的内存仍然可以通过列表访问,因此没有内存泄漏。

仅仅因为没有基于引用计数的泄漏,并不意味着你没有在字典“缓存”中填充某个内容并忘记它;这些不会显示为泄漏,因为有对它的有效引用(dict仍然有效,对其所有子项的引用也是有效的)。您还需要查找对对象的有效但不必要的引用

最简单的方法是让它运行太长时间,然后按类型对对象计数排序,看看谁有一个巨大的数字——然后,跟踪参考图(在Obj-C中可能很难?)。如果Instruments没有直接执行此操作,您完全可以编写DTrace脚本来执行此操作。

重申:

char *str1 = malloc(1000);
char *str2 = malloc(1000);
  .
  .
  .
char *str1000 = malloc(1000);
不是内存泄漏,而是

char *str1 = malloc(1000);
char *str1 = malloc(1000);  //Note! No free(str1) in between!

是内存泄漏

关于核心数据内存管理的信息是很好的信息,从技术上讲,Arthur Kalliokoski的答案是一个很好的答案:韭菜和对象分配之间的区别。我这里的特殊问题与一个明显已知的bug有关,该bug在模拟器的一个按钮上带有setBackgroundImage,它会造成内存“泄漏”,因为它不会释放UIImage的内存。

这听起来可能是以下几件事之一:

  • 释放后未将内存返回操作系统。这是C运行时的常见设计。当您进行分配时,C运行时会分配更多内存供其使用,并返回一块内存供您使用。当您执行释放操作时,C运行时只是将其标记为释放,但不会将其返回到操作系统。因此,如果泄漏工具正在读取操作系统级统计信息而不是C运行时统计信息,那么泄漏工具将无法报告内存使用量的相应减少

  • 泄漏工具内存报告的误导性值。泄漏工具可能会查看与C运行时不同的值,并且报告的值会引起您的关注,即使没有任何问题(正如人们试图在Windows中使用任务管理器检测泄漏,并对结果感到非常困惑,因为它对于该工作来说确实是一个非常糟糕的工具)

  • 碎片化。您的应用程序可能存在内存碎片问题。也就是说,当您分配,然后取消分配,然后分配时,后续尝试的分配比取消分配留下的“漏洞”要大。当这种情况发生时,您会分割内存空间,留下不可用的漏洞,阻止大型连续内存块,并迫使使用越来越多的内存空间,直到内存耗尽。这是一种病理状态,修复通常是特定于应用程序的


我认为这三个建议中的第一个最有可能是正在发生的事情。

我在对象图中强调了这一点,所有图像都有自己的实体。但是,如果我正在向coreData添加大量新项目,包括图像,图像数据在内存中,因为我刚刚添加了它,我如何“取消故障”某些内容以从内存中删除实体?找到“重新故障”的条目,试一试。不确定这是否适用于你的应用程序,如果适用,你可能已经涵盖了它,但你应该只在需要全尺寸图像时加载全尺寸图像。例如,tableview将在行单元格的缩略图中显示多个MEG的全尺寸图像。它在视觉上看起来很小,但在记忆方面,它是巨大的。如果可能,您应该创建和存储缩略图,这些缩略图的分辨率仅能满足实际显示的大小。然后只在需要的地方加载完整图像,然后立即进行处理。谢谢你的建议,是的,我就是这么做的,我存储了两种图像大小,一个缩略图和一个完整大小的图像,并且只显示完整大小