2011-11-14 35 views
2

在寻找内存泄漏时,我发现了一件奇怪的事情,我不知道它是否正常。这是内存泄漏还是正常行为?

为了查找内存泄漏,我创建了一个小的测试应用程序与新的一个按钮和一个按钮检查这样做:

List<WeakReference> WeakReferences = new List<WeakReference>(); 

private void Button_New(object sender, RoutedEventArgs e) 
{ 
    WeakReferences.Add(new WeakReference(new ObjectUnderTest())); 
    // Adding a bunch of other objects to test here 
} 
private void Button_Check(object sender, RoutedEventArgs e) 
{ 
    GC.Collect(); 
    GC.WaitForPendingFinalizers(); 
    GC.Collect(); 

    int AliveCounter = 0; 
    foreach (var item in WeakReferences) 
    { 
     if (item.IsAlive) 
     { 
      AliveCounter++; 
      Debug.WriteLine("Object " + item.Target.GetType().ToString() + " still alive!"); 
     } 
    } 
    if (AliveCounter > 0) 
    { 
     MessageBox.Show(AliveCounter.ToString() + " objects still alive!"); 
    } 
    else 
    { 
     MessageBox.Show("No objects alive!"); 
    } 
} 

我大部分的测试对象得到正确的垃圾收集在这种情况下,但有是一些仍然活着的物体。

经过更多测试后,我发现这些对象确实被垃圾回收,但只有在单击检查按钮之前切换到另一个应用程序。

你认为,这是正常的行为,还是这是一个内存泄漏,我必须解决?

附加信息: 目前我认为这确实是一个问题,但也许它不会在我们的生产代码中发生。

  • 添加上新点击100个对象给出后约650 objetcs内存异常,所以GC不会收集,即使所需的内存用于其他目的。
  • AddMemoryPressure不会使任何更确定性。
  • 使用鼠标点击切换应用程序并无帮助,只有使用ALT + TAB进行切换才有用!
  • 有时它有助于在我的测试应用程序中打开一个新窗口。
+3

如果他们最终得到收集,它不能是一个“泄漏” - 这听起来更像是“我希望GC更积极” –

+0

这只是一个测试应用程序,因为我们有很多泄漏,主要是因为忘记注销的事件。在这个测试应用程序中,如果GC更具侵略性,那会更好。但对于我们的真实应用程序,我只想知道我现在是否可以确定,如果需要,可以收集这些对象。我们不想告诉GC何时收集,我们只是想确保它们不会泄漏。 我们真正的应用程序将全天候运行,所以如果它泄漏将是一个问题。 – MTR

回答

5

GC.Collect()在调用时没有GCCollectionMode参数,那么GCCollectionMode.Default使用它,在CLR的大多数版本,相同GCCollectionMode.Forced,迫使收集发生。为确保您强制收集,请尝试拨打GC.Collect(GCCollectionMode.Forced)

如果你还是找的对象被关押活着,这可能是由于与并发收集你的线程赛车(并发收集是在大多数环境中的默认值)或也许你的ObjectUnderTest类型是自我复活或具有复杂参考路径混淆了GC的第一遍(一种不太可能的情况,但你永远不知道)?

在一般说明中,GC将决定何时是收集给定对象的最佳时间,并且此行为是非确定性的(除非您致电GC.Collect(GCCollectionMode.Forced)或等效)。在某些边缘情况下,有必要影响垃圾收集器的行为,但在大多数情况下,最好让GC做这件事,而不用担心它的有效性。这通常是足够高效的,并且使其更有效地操作可能相当困难且涉及。

+2

如果您调用GC.Collect,那么它是确定性的... GCCollectionMode.Default(通过MSDN)与GCCollectionMode相同。强制,意思是“强制垃圾收集立即发生”。这非常确定。 –

+0

它强制垃圾收集立即发生,但垃圾收集在其选择中仍然是独立的。因此,它可以决定暂时不释放缓冲区。或不?我认为亚当在这个意义上打算“非确定性”,比如“并不总是做同样的事情”。 – gd1

+0

我认为马克有一个观点。我编辑了答案。 –