您的位置:首页 > 其它

.net垃圾回收学习【Back to Basics: Memory leaks in managed systems】【翻译&&学习】

2011-08-27 17:24 801 查看
From: http://blogs.msdn.com/b/abhinaba/archive/2010/01/05/back-to-basics-memory-leaks-in-managed-systems.aspx

有些人问他的Managed application为什么会内存一直在不停的增加,而且这很明显的是内存泄漏的标志,这些人都持有这个观点he is using .net and hence there should surely be no leaks。其他一些人也持有类似的观点。

然而这个观点是不正确的,可以通过以下两篇文章了解GC的工作机制:

http://blogs.msdn.com/abhinaba/archive/2009/01/20/back-to-basics-why-use-garbage-collection.aspx.

http://blogs.msdn.com/abhinaba/archive/2009/01/25/back-to-basic-series-on-dynamic-memory-management.aspx

需要注意的是: GC只会移除那些不再使用的对象,不幸运的,很容易写出来引用没有完全清除掉的代码。

示例1: event handling( discussed in more detail here)

考虑如下代码:

EventSink sink = new EventSink();

EventSource src = new EventSource();


src.SomeEvent += sink.EventHandler;

src.DoWork();


sink = null;

// Force collection

GC.Collect();

GC.WaitForPendingFinalizers();

在这个例子中, 当强制执行GC的GC.collect的时候,并没有任何引用指向了sink对象(明确的将sink对象设置为NULL),然而,即使是这样,Sink仍然不会被回收。原因是sink正被当作一个event的Handler来使用,因此Src对象持有对sink的引用(这样当someEvent触发的时候,他能够调用sink.EventHandler)并且组织了它被回收。

示例2: Mutating objects in collection(discussed here)

这里有更深入的示例. 两年前看到一个讨论是当对象被放到一个Dictionary中,然后被取出来,使用,丢掉,现在获取的方式是通过Object key.示例如下:

创建一个对象并且放入到Dictionary

通过Object Key获取对象并使用。

调用Object上的方法。

随后再次通过key获取Object并且移除他。

现在对象并不是不可变的了,在使用对象的过程中,修改了对象的某个字段,而这个被修改的字段是用来计算对象的Hash Code的。这意味着在移除对象的过程中并没有找到对象而对象一直存在在Dictionary中。 你知道当修改一个对象的用于计算GetHashCode的字段为什么会导致将对象从Dictonary中移除会失败么?看这里:http://blogs.msdn.com/abhinaba/archive/2007/10/18/mutable-objects-and-hashcode.aspx

还有更多的的例子。

现在我们得出来的结论是:在托管的内存管理中,内存泄漏也是很普遍的情况。通常出现这种情况的原因是恰巧有些应当被清除掉的引用没有被明确的清楚掉,当GC找到这些对象的时候,发现这些对象仍然被其他对象引用,所以不会回收这些对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐