C#用内存泄漏收集对象的垃圾

时间:2011-02-22 03:13:33

标签: c# memory-leaks garbage-collection

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

该对象在我的命令行应用程序中初始化为我的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(N.B.它需要一两秒才能将词典从文件加载到内存中)

4 个答案:

答案 0 :(得分:1)

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

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

了解:

  1. 如果你正确使用他们的库,或者你做错了什么导致内存泄漏。
  2. 如果他们的库即使按预期使用也会泄漏内存,他们可以修复泄漏吗?
  3. 附加说明:如果第三方库是本机的,并且您必须使用互操作,则可以使用Marshal.ReleaseComObject释放非托管内存。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

我建议如果您可以使用内存分析器,就可以使用它。内存分析器将允许您暂停程序,单击一个类,然后查看该类的对象列表。然后,可以单击一个对象并查看它是如何创建的,以及从根开始到该对象的“路径”(例如,有一个静态类foo,它保存对一个条形的引用,它包含对boz的引用,提到了一个真正的大事。通常情况下,看到这一点就会明确需要做些什么才能打破链条。

答案 3 :(得分:0)

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