废弃内存与内存泄漏有什么区别?

时间:2012-01-12 18:18:15

标签: objective-c ios memory-management memory-leaks abandoned-memory

两者完全相同,只是“废弃的内存”指的是泄漏的整个对象图而不是单个对象。正确?

3 个答案:

答案 0 :(得分:27)

首先,您需要了解“内存对象图”或“应用程序对象图”(或简称为“对象图”,因为它适用于已分配的缓冲区)的概念。在这种情况下,“对象”指的是应用程序中的任何分配,无论是对象还是简单的malloc() ed缓冲区。 “图形”部分,如果它是任何对象可以包含对指向其他对象的指针。

应用程序的“活动对象图”是可以直接或间接从应用程序中的各个“根”到达的所有分配。 “root”本身代表对象的实时引用,无论其他任何内容是否明确引用了根。

例如,全局变量是根;通过引用一个对象,根据定义,全局变量使该对象成为应用程序的实时对象图的一部分。并且,通过暗示,全局变量引用的对象的任何对象也被认为是活动的;没有泄露。

堆栈也是如此;任何线程的实时堆栈引用的任何对象本身都被认为是实时的。

考虑到这一点,泄漏废弃的记忆实际上确实有两个不同的含义。

泄漏

泄漏是一段内存,没有引用应用程序实时对象图中任何活动对象的分配

即。内存无法访问,因此无法再次引用它(禁止错误)。这是死记忆。

请注意,如果对象A指向对象B而对象B指向A,但实时对象图中没有任何内容指向A或B,则它仍然是泄漏。如果B-> A和A-> B参考都是保留的参考文献,那么您将获得一个保留周期&泄漏。

被遗弃的记忆

应用程序的实时对象图中的分配但由于应用程序逻辑问题而无法再访问被视为已放弃,但未被泄露。

例如,假设您有一个缓存,其条目是NSData的实例,这些实例是从某个URL下载的,其中URL包含URL中的会话ID(常见模式),并且使用了会话ID + URL作为查找缓存中的东西的关键。现在,假设用户注销,导致会话ID被销毁。如果缓存未被删除特定于该会话ID的所有条目,则所有这些NSData对象将被放弃,但不会泄露,因为它们仍然可以通过缓存到达。


实际上,在这两者之间区别对待这种解决方案几乎没有什么用处,因为修复要么需要非常不同的策略。

修复泄漏是为了找出额外保留的来源(或者在free()基于泄漏的情况下可能需要插入malloc()的遗失调用)。由于无法从实时对象图中找到检测到的泄漏,因此修复泄漏确实非常简单。

由于几个原因,修复废弃的内存可能会相当棘手。

首先,内存仍然可以从实时对象图中访问。因此,根据定义,您的应用程序中存在一个保持内存存活的算法问题。寻找和修复通常会更加困难,并且可能会造成破坏性,而不仅仅是修复泄漏。

其次,可能存在对废弃分配的非归零非保留弱引用。也就是说,如果你弄清楚在哪里修剪强引用并使分配实际消失,那并不意味着你的工作已经完成;如果有任何剩余的非归零弱引用,它们现在将是悬空指针和..... BOOM


正如阿米特指出的那样,Heapshot Analysis非常擅长发现泄漏,遗弃内存以及 - 非常重要 - 整体上“不良内存增长”。

答案 1 :(得分:3)

不确定是否存在标准术语,但也有可能存在具有引用的内存,但永远不会被使用。 (Leaks乐器的Heap Shot功能可以帮助追踪它。)我称之为“膨胀”,以区别于真正的泄漏。两者都是浪费的记忆。

答案 2 :(得分:1)

被遗弃的内存是内存泄漏。快照分析将帮助您找到不受欢迎的内存增长。这是一篇很好的文章。 http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/