【问题标题】:C# Collect garbage of object with memory leakC# 收集具有内存泄漏的对象的垃圾
【发布时间】:2011-02-22 03:13:32
【问题描述】:

我正在使用我没有创建的第 3 方对象,随着时间的推移会消耗大量资源。该对象不应该以任何方式包含状态,它只是执行计算。尽管如此,每次我调用这个对象的特定函数时,都会消耗更多的内存。几个小时后,我的程序分配了千兆字节的内存。

在我的命令行应用程序中,该对象最初被初始化为我的 Program 类的静态成员。我发现,如果我将整个程序包装在一个类中,并时不时地重新初始化它,那么旧的(和臃肿的)对象不会被 GC 分配,而一个新的更小的对象会替换它。

我的问题是这种方法非常笨拙并且破坏了我的程序流程。

还有其他方法可以处理对象吗?我相信 GC.Collect() 只会处理无法访问的代码。无论如何我可以使对象“无法访问”吗?

编辑:根据要求,代码:

static ILexicon lexicon = new Lexicon();

...

lexicon.LoadDataFromFile(@"lexicon.dat", null);

...

    byte similarityScore(string w1, string w2, PartOfSpeech pos, SimilarityMeasure measure)
    {
        if (w1 == w2)
            return 255;
        if (pos != PartOfSpeech.Noun && pos != PartOfSpeech.Verb)
            return 0;

        IList<ILemma> w1_lemmas = lexicon.FindSenses(w1, pos);
        IList<ILemma> w2_lemmas = lexicon.FindSenses(w2, pos);
        byte result;
        byte score = 0;

        foreach (ILemma w1_lemma in w1_lemmas)
        {
            foreach (ILemma w2_lemma in w2_lemmas)
            {
                result = (byte) (w1_lemma.GetSimilarity(w2_lemma, measure) * 255);
                if (result > score)
                    score = result;
            }
        }

        return score;
    }

在调用similarityScore 时,会为lexicon 的私有成员分配更多内存。它没有实现 IDisposable,也没有明显的清除内存的功能。该库基于 WordNet,并使用一种算法在上位词树中查找路径长度来计算两个单词的相似度。除非有缓存,否则我看不出它为什么需要存储任何内存。可以肯定的是,我无法改变它。我几乎可以肯定我的代码没有任何问题。我只需要在 lexicon 变得太大时处理它(注意,将词典从文件加载到内存需要一两秒钟)

【问题讨论】:

  • 对象是托管代码还是非托管代码?
  • 咨询供应商并寻求帮助。可能只是您错误地使用了该库,或者它确实存在内存泄漏问题。
  • 能否在VS中插入断点并检查词典实例的私有变量?您也许可以帮助您的供应商找到错误并修复它。

标签: c# memory-leaks garbage-collection


【解决方案1】:

如果对象没有实现 IDisposable 并且您想将其推出范围之外,您可以将对其的所有引用设置为 null,然后使用 GC.Collect() 强制进行垃圾回收。

GC.Collect() 非常昂贵。如果您必须经常这样做,您可能需要考虑联系供应商。

找出:

  1. 如果您正确使用了他们的库,或者您做错了什么导致内存泄漏。
  2. 如果他们的库在按预期使用时仍存在内存泄漏,他们能否修复泄漏?

附加说明:如果 3rd 方库是本机的并且您必须使用互操作,则可以使用 Marshal.ReleaseComObject 来释放非托管内存。

【讨论】:

  • 不实现 IDisposable。我将尝试将对象设置为空。我想我可以负担得起每五分钟运行一次 GC.Collect() ,现在我的应用程序根本无法运行很长时间。该图书馆是一项非常利基的任务,并且是免费的,我怀疑我会和作者一起去任何地方。谢谢。
【解决方案2】:

您可以尝试调用Dispose() 方法。这会使对象无法使用,因此您必须实例化另一个对象。我假设你的程序在一个循环中,所以它可以是一个循环变量,在底部调用 dispose。

【讨论】:

  • 假设该类实际上实现了 IDisposable 或提供了一些释放本机资源的方法(并且还假设这就是问题所在)。
  • -1 他对实现 IDisposable 的对象只字未提。
  • 他也没有说没有实现 IDisposable。关键是它是一个潜在的解决方案,假设确实如此。
【解决方案3】:

我建议,如果您可以使用内存分析器,请使用它。内存分析器可以让您暂停程序,单击一个类,然后查看该类的对象列表。然后可以单击一个对象并查看它是如何创建的,以及从根到该对象的“路径”(例如,有一个静态类 foo,它包含对 bar 的引用,它包含对 boz 的引用,包含对真正大事物的引用)。通常,看到这一点就会清楚地知道需要做什么才能打破链条。

【讨论】:

    【解决方案4】:

    您可以从 wordnet 存储库下载源代码并修改代码,因为它是开源的。

    【讨论】:

      猜你喜欢
      • 2012-01-03
      • 2018-05-10
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 2010-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多