我正在为SDK 3.2中的应用程序运行一些内存分析,我使用'Leak'分析器查找我的所有内存泄漏并将所有内存插入。这是一个scrollView navigationController应用程序,其中有瓷砖,你点击一个瓷砖进入瓷砖的新视图等等,我可以深入多层次,一直回到顶部,'泄漏'剖析器说一切很酷。
但是,如果我在“ObjectAlloc”分析器中观察内存占用,随着我的深入(这似乎是合理的),内存占用量会不断上升,但当我退出视图时,内存占用量不会下降我期待。
我知道这是一个模糊的应用程序描述,但我无法准确发布数十亿行代码:)另外应该注意我正在使用coreData存储图像数据,因此数据库正在增长选择更多节点时的大小,如果/何时从内存中释放,则为dunno。
是什么给出了?
答案 0 :(得分:4)
听起来这可能是以下几点之一:
释放后内存未返回给操作系统。这是C运行时的常见设计。当您进行分配时,C运行时会为其使用分配更多内存,并返回一大块供您使用。当您执行空闲时,C运行时只是将其标记为已释放但不会将其返回到操作系统。因此,如果泄漏工具正在读取操作系统级统计信息而不是C运行时统计信息,则泄漏工具将无法报告相应的内存使用量减少。
泄漏工具存储器报告的误导值。泄漏工具可能会查看与C运行时不同的值,并报告即使没有任何错误也会引起您关注的值(正如人们尝试在Windows中使用任务管理器检测泄漏并且对结果非常困惑,因为它对于那项工作来说,这是一个非常糟糕的工具。)
碎片。您的应用程序可能存在内存碎片问题。也就是说,当你分配,然后解除分配然后分配时,后续的尝试分配大于解除分配留下的“漏洞”。当发生这种情况时,您会分割内存空间,留下不可用的漏洞,防止大的连续内存块,并强制使用越来越多的内存空间,直到内存不足为止。这是病理状况,修复通常是特定于应用的。
我认为这三个建议中的第一个很可能是正在发生的事情。
答案 1 :(得分:3)
根据您在Core Data中构建对象图的方式,它的内存使用量会出乎意料地增大。
常见的错误是将对象存储在复杂且经常出现故障(加载到内存中)的实体中。这会导致在引用实体的任何其他部分时将大blob加载/保留在内存中。随着对象图增长,它会占用越来越多的内存,除非您主动删除对象然后保存图形。
例如:您有一个拥有大量文字信息的个人实体,例如:姓名,地址等以及大照片。如果您将照片作为人物实体的属性,则只要人员实体出现故障,它就会在内存中。如果获得属性名称,则photo属性也在内存中。
为了避免这种情况,blob应该在他们自己的实体中,然后链接到关系中的其他实体。由于关系对象在被直接调用之前不会出现故障,因此在需要之前它们可以保持内存不足。
答案 2 :(得分:1)
仅仅因为没有基于refcount的泄漏,并不意味着你没有在字典“缓存”中填充某些内容并忘记它;那些不会显示为泄漏,因为它有有效的引用(dict仍然有效,所有子代的引用也是如此)。您还需要查找对象的有效但不必要的引用。
最简单的方法是让它运行太久,然后按类型对对象进行排序,看看谁有一个巨大的数字 - 然后,追踪参考图(在Obj-C中可能很难?)。如果Instruments不直接执行此操作,您绝对可以编写DTrace脚本。
答案 3 :(得分:1)
重申:
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!
是内存泄漏
答案 4 :(得分:1)
关于核心数据内存管理的信息是很好的信息,从技术上讲,Arthur Kalliokoski的答案是一个很好的答案:韭菜和对象分配之间的区别。我在这里的特殊问题与模拟器中按钮上的setBackgroundImage明显已知的错误有关,它会创建一个内存“泄漏”,因为它不会释放永久释放UIImage的内存。
答案 5 :(得分:0)
您可以拥有一个不断增长的程序,而不必泄漏内存。假设您从输入中读取单词并将它们存储在链接列表中动态分配的内存块中。当您阅读更多单词时,列表会不断增长,但所有内存仍然可以通过列表访问,因此没有内存泄漏。