内存泄漏,不确定是否管理对象

时间:2011-04-27 14:19:29

标签: c# garbage-collection

我在C#中遇到内存泄漏问题。当没有新对象应该被创建时,我看到进程管理器中的内存使用量增加了10-20mb(以及更多)。

q1)我认为GC会自动删除托管对象。但是当我使用dotTrace分析内存使用情况时,我写的基本对象似乎有+ 10k个实例(在show new / dead差异中)。如果这是c ++,我找到了泄漏的地方,

public void TriggerEvent(string tEvent)
{
    oVariable tVar = GetVar(tEvent);
    if (tVar != null)
        sVariableParser.TriggerEvent(tVar);
    else
    {            
        tVar = new oVariable("@CXZ_TEMP_VAR", tEvent, 0, this);
        tVar._BlockDependancies = true;
        sVariableParser.TriggerEvent(tVar);
    }
}

oVariable定义为

class oVariable : IComparable 

似乎GC没有删除新的oVariables,我想知道我是否需要实现oVariable作为IDisposable并进行特定的系统调用以确保GC收集它? oVariable中还有一些其他自定义对象,但我的印象是不应该使用任何外部(没有COM对象等)的简单对象应该自动管理,或者我错了,我已经创建了非托管数据结构?

q2)即使dotTrace内存显示了许多新的oVariables,其中应该为零(可能是GC是懒惰的),我仍然感觉内存泄漏可能来自Windows窗体,特别是DataGridViews。我想知道是否有人可以告诉我是否需要在使用

调用DGV更新/重绘后进行任何特定的内存释放函数调用
tGridView.Invoke(new UpdateGridViewCallBack(RedrawGlobalsViewGridView), tGridView);

我认为新的回电会自行清理。

3 个答案:

答案 0 :(得分:4)

首先,不要调用GC.Collect()它会强制垃圾收集,但有一些讨厌的副作用。例如,它会将尚未准备好进行垃圾回收的所有内容推回一代并延迟其收集。 MS有信息about generations

其次,GC只会在没有引用的情况下收集对象。

因此,假设您的sVariableParser是一个成员变量,它包含对您的tVar的引用。当GC运行时,它会看到VariableParser依赖于tVar而不是让它继续运行。

想象一下,你有这样的事情:

public class House
{
   public Person Resident1 {get; set;}
}

public class Person
{
   public string Name {get; set;}
}

然后在您的代码中

House.Resident1 = new Person {name = "John Calvin"};

当垃圾收集运行时,它无法清除与Resident1关联的Person对象,直到House超出范围且不再使用。

所以这就是说,GC会清理你的引用,但我猜你有一些代码保留在你的tVar上,而你却没有意识到它。

答案 1 :(得分:2)

首先,GC不受任何人的直接控制,而是运行时的;它只会在运行时认为它应该运行时运行。这意味着计划进行清理的对象可能会持续几秒甚至几分钟,直到内存条件指示应该执行清理。

然而,等待清理的10,000个死实例听起来像是内存泄漏。有些事要检查:

oVariable是否包含或引用非托管或IDisposable对象?如果是这样,oVariable应该实现IDisposable并执行清理,释放对它不“拥有”的对象的引用,和/或处理它控制的对象。您可以使用一种模式来避免必须显式调用Dispose();看看http://www.codeproject.com/KB/cs/idisposable.aspx

oVariable是否订阅其他对象的任何事件?只要具有事件的对象在内存中,任何已将其处理程序添加到事件中的oVariable将保留在内存中,因为对于该方法的引用将使该对象保持“活着”,就GC而言。同样,您应该创建一个IDisposable实现,并让对象从它侦听的任何事件中删除。

最后,我在你对另一篇文章的评论中注意到你保持了向上和向下的等级关系,以及其他oVariables。只要oVariable存在于任何列表中,就会引用它。我会三重检查所有添加和删除这些列表中的实例的代码;你忘了在某个地方移除物体,所以它们无限期地徘徊。再次,处置oVariable应该包括(1)从任何/所有Master oVariables中删除对变量的任何引用作为Slave,(2)从任何/所有Slave中删除对变量的任何引用,最后( 3)清除变量的主和从列表。只有当对象在内存中完全“孤立”时,GC才会破坏它。

答案 2 :(得分:1)

oVariable的内部实施是什么样的?如果您使用的是继承IDisposable的任何资产,则需要关闭它们(或使用using块)以确保它们得到妥善处置。