如果我有一个垃圾收集器跟踪分配的每个对象,并且一旦它们不再有可用的引用就会释放它们,你还会有内存泄漏吗?
考虑到内存泄漏是没有任何参考的分配不是不可能的,或者我错过了什么?
编辑:那么我所谓的内存泄漏是你在代码中不再引用的分配。你仍然参考的大量累积分配不是我在这里考虑的泄漏。
我也只是谈论正常的技术状态G.C.,已经有一段时间但是我知道像周期性参考这样的情况不会绊倒它们。我不需要任何语言的具体答案,这只是来自我与朋友的对话。我们讨论的是Actionscript和Java,但我并不关心那些特定的答案。
Edit2:从它的声音来看,似乎没有任何理由代码可以完全失去引用分配的能力而没有GC能够拿起它,但我还在等待更多称重。
答案 0 :(得分:9)
如果您的问题确实如此:
考虑到内存泄漏是没有任何引用的分配 那是不可能的,还是我错过了什么?
然后答案是“是的,那是不可能的”,因为正确实现的垃圾收集器将回收所有没有活动引用的分配。
但是,在(例如)Java中肯定会出现“内存泄漏”。我对“内存泄漏”的定义是一个仍然有一个有效引用的分配(因此 >>不会被垃圾收集器回收)但是程序员没有知道对象不可回收(即:对于程序员来说,这个对象已经死了,应该被回收)。一个简单的例子是这样的:
ObjectA - >对象B
在此示例中,ObjectA是代码中活动使用的对象。但是,ObjectA包含对ObjectB的引用,它实际上已经死了(即:已经分配并使用了ObjectB,现在,从程序员的角度看,已经死了),但是程序员忘了将ObjectA中的引用设置为null。在这种情况下,ObjectB已被“泄露”。
听起来不是一个大问题,但有些情况下这些泄漏是累积的。让我们假设ObjectA和ObjectB实际上是同一个类的实例。并且每次使用这样的实例时,程序员忘记将引用设置为null的这个问题就会发生。最终你最终得到这样的东西:
ObjectA - > ObjectB - > ObjectC - > ObjectD - > ObjectE - > ObjectF - > ObjectG - > ObjectH - >等...
现在ObjectB到ObjectH都泄露了。这样的问题(最终)会导致程序崩溃。即使有正确实施的垃圾收集器。
答案 1 :(得分:2)
要确定程序是否存在内存泄漏,必须首先定义泄漏是什么。如果存在某些状态S
和一系列输入I
,我会将程序定义为内存泄漏:
完全在垃圾收集框架内运行的程序绝对有可能出现如上所述的内存泄漏。可以发生的常见方式是使用事件订阅。
假设线程安全集合公开CollectionModified
事件,其IEnumerator<T>
方法返回的IEnumerable<T>.GetEnumerator()
在创建时订阅该事件,并取消订阅Dispose
;该事件用于允许枚举即使在修改集合时也能合理地进行(例如,确保在整个枚举过程中对象在集合中的连续性将仅返回一次;在部分期间存在的对象将返回不超过一次) 。现在假设创建了该集合类的长期实例,并且某些特定输入将导致它被枚举。如果CollectionModified
事件拥有对每个非处置IEnumerator<T>
的强引用,则重复枚举该集合将创建并订阅无限数量的枚举器对象。内存泄漏。
答案 2 :(得分:0)
内存泄漏并不仅仅取决于垃圾收集算法的效率,如果你的程序持有生命周期很长的对象引用,比如实例变量或静态变量而不使用,你的程序会有内存泄漏
引用计数有一个已知的循环引用问题,意思是
Object 1 refers to Object 2 and Object 2 refers to Object 1
但没有其他人引用对象1或对象2,引用计数算法在这种情况下将失败。
由于您正在处理垃圾收集器本身,因此值得阅读different implementation strategies。
答案 3 :(得分:0)
您可以通过另一种方式使用GC进行内存泄漏:如果您使用conservative garbage collector天真地扫描内存以及看起来像指针的所有内容,则不会释放它“指向”的内存,你可以留下无法访问的内存。