简体   繁体   English

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

[英]C# Collect garbage of object with memory leak

I am using a 3rd-party object I didn't create that over time consumes a lot of resources. 我使用的不是第三方对象,随着时间的推移,它会消耗大量资源。 This object shouldn't in any way contain a state, it simply performs a calculation. 该对象不应以任何方式包含状态,它只是执行计算。 Despite this fact, everytime I call a specific function of this object a little more memory is consumed. 尽管如此,每次我调用该对象的特定功能时,都会消耗更多的内存。 A few hours later, and my program is sitting at gigabytes of allocated memory. 几个小时后,我的程序正坐在千兆字节的分配内存中。

The object was origionaly initialized as a static member of my Program class in my command-line application. 最初,该对象已初始化为我的命令行应用程序中Program类的静态成员。 I have found that if I wrap my entire program in an class, and reinitialize it every now and again, the older (and bloated) object is unallocated by GC and a new smaller object replaces it. 我发现,如果我将整个程序包装在一个类中,并不时地对其进行初始化,则GC不会分配旧的(膨胀的)对象,而新的较小的对象将替换它。

My issue is this method is quite clumsy and ruins the flow of my Program. 我的问题是这种方法很笨拙,并且破坏了我程序的流程。

Is there any other way you can dispose of an object? 还有其他处置对象的方法吗? I am lead to believe GC.Collect() will only dispose unreachable code. 我相信GC.Collect()只会处理无法访问的代码。 Is there anyway I can make an object 'unreachable'? 无论如何,我可以使对象“无法到达”吗?

Edit: As requested, the code: 编辑:根据要求,代码:

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;
    }

As similarityScore is called, more memory is allocated to a private member of lexicon . 调用lexiconlexicon更多内存分配给lexicon的私有成员。 It does not implement IDisposable and there are no obvious functions to clear the memory. 它没有实现IDisposable,也没有明显的功能来清除内存。 The library is based on WordNet, and uses an algorithm to find path lengths in the hypernym tree to calculate the similarity of two words. 该库基于WordNet,并使用一种算法在上标树中查找路径长度,以计算两个单词的相似度。 Unless there is caching, I can't see why it would need to store any memory. 除非有缓存,否则我看不到为什么它需要存储任何内存。 What is for sure, is I can't change it. 可以肯定的是,我无法更改它。 I'm almost certain there is nothing wrong with my code. 我几乎可以肯定我的代码没有错。 I just need to dispose of lexicon when it gets too large (NB it takes a second or two to load the lexicon from file to memory) 我只需要在太大的情况下处理lexicon (注意,将词典从文件加载到内存需要花费一两秒钟的时间)

If the object doesn't implement IDisposable and you want to push it out of scope you can set all references to it to null and then the force garbage collection with GC.Collect(). 如果该对象未实现IDisposable,而您想将其推出范围,则可以将对其的所有引用都设置为null,然后使用GC.Collect()强制进行垃圾回收。

GC.Collect() is very expensive. GC.Collect()非常昂贵。 If you're going to have to do this frequently, you might want to consider contacting the vendor. 如果您将不得不经常执行此操作,则可能需要考虑与供应商联系。

Find out: 找出:

  1. If you are using their library correctly, or is there something you're doing wrong that's causing the memory leak. 如果您正确使用了它们的库,或者您做错了什么,则导致内存泄漏。
  2. If their library is leaking memory even when used as intended, can they fix the leak? 如果即使按预期使用它们的库仍在泄漏内存,是否可以解决泄漏问题?

Additional note: If the 3rd party library is native and you're having to use interop, you can use Marshal.ReleaseComObject to free unmanaged memory. 附加说明:如果第3方库是本机库,并且您必须使用互操作,则可以使用Marshal.ReleaseComObject释放非托管内存。

you could try calling the Dispose() method. 您可以尝试调用Dispose()方法。 This would make the object unusable, so you would have to instantiate another one. 这将使该对象不可用,因此您必须实例化另一个对象。 I assume your program is in a loop, so it can be a loop variable with the call to dispose at the bottom. 我假设您的程序处于循环中,因此它可以是一个循环变量,其调用位于底部。

I would suggest that if you can get your hands on a memory profiler, you use it. 我建议,如果可以使用内存分析器,则可以使用它。 A memory profiler will let you pause your program, click on a class, and and see a list of objects of that class. 内存分析器将使您暂停程序,单击一个类,然后查看该类的对象列表。 One can then click on an object and see how it was created, and the "path" to that object from a root (eg there's a static class foo, which holds a reference to a bar, which holds a reference to a boz, which holds a reference to a reallybigthing). 然后,可以单击一个对象并查看它是如何创建的,以及从根到该对象的“路径”(例如,有一个静态类foo,其中包含对bar的引用,其中包含对boz的引用,引用了一个非常重要的内容)。 Often, seeing that will make it clear what needs to be done to break the chain. 通常,看到这一点将使您清楚需要做些什么来打破链条。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM