东西阻塞了我的记忆,程序挂起在GC.Collect()或GC.GetTotalAmountOfMemory(true)

Ste*_*ler 4 c# garbage-collection memory-leaks block

无论何时我打电话给整个节目GC.Collect()GC.GetTotalAmountOfMemory(true)整个节目都挂了.现在,我知道你要说什么:不要打电话GC.Collect()给GC照顾自己.问题是:在我的情况下,内存中没有东西,GC无法摆脱它.

我不知道它可能是什么(项目是大/旧).我希望有人知道如何获取有关GC尝试做什么的信息(显然不能做),以便我可以搜索问题或者像内存分析器这样的东西在这里有任何帮助(我目前有ANTS)安装)和我应该搜索什么.

*编辑我完全忘记的东西:有时当我调用GC的两种方法之一时,内存使用量增加~10千字节/秒

*edit2我要纠正自己:GC.Collect()运行得很好.只有GC.GetTotalMemory(true)挂起.GC.GetTotalMemory(false)也可以正常工作.

*edit3和是,你们中的一些人已经说过了:它似乎是某个地方的终结者.当我运行WaitForPendingFinalizers()时,它只是坐在那里,什么都不做.

好了,现在我完全糊涂了:当我输入一个GC.GetTotalMemor(true)GC.WaitForPendingFinalizers()到Visual Studio的即时窗口后,我暂停调试器,程序挂起(这就是我所做的全部时间......我现在觉得自己很蠢).当我将它添加到我通常的源代码并编译它时,它工作得很好.

抱歉整个模糊,似乎记忆漏洞有另一个原因.

Fel*_* K. 7

你是否覆盖任何终结者?当终结器未返回时(可能您在任何时候等待另一个线程)应用程序可能会挂起.该GC.Collect()调用终结,但其不退还,因为它等待终结返回.这可能也是导致内存泄漏的原因,因为GC无法完成垃圾回收.

你应该能够调试它,当GC收集时你按下"暂停"它应该显示它挂起的堆栈跟踪.如果一切都出错了,您可能需要检查应用程序挂起的反汇编.

GetTotalMemory(真)

这种方法强制垃圾收集,所以它就像是一样GC.Collect().

更新

让我们来看看GetTotalMemory:

public static long GetTotalMemory(bool forceFullCollection)
{
    long totalMemory = GC.GetTotalMemory();
    if (!forceFullCollection)
    {
        return totalMemory;
    }
    int remainingSteps = 20;
    long lastMemory = totalMemory;
    float num4;
    do
    {
        GC.WaitForPendingFinalizers();
        GC.Collect();
        totalMemory = lastMemory;
        lastMemory = GC.GetTotalMemory();
        num4 = (float)(lastMemory - totalMemory) / (float)totalMemory;
    }
    while (remainingSteps-- > 0 && (-0.05 >= (double)num4 || (double)num4 >= 0.05));

    return lastMemory;
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的那样GetTotalMemory,等待终结器,所以它必须是一个挂起应用程序的终结器.GC.Collect()在终结器完成时调用,并且永远不会被调用,因为它从未通过该行.

在你的应用程序的任何一点(不安全的代码?另一个线程?)有一些东西分配了大量的内存,而GC从来没有机会清理现有的内存.

放弃

这是一个纯粹的猜测,我不知道如果GC处理这种情况,但我认为它不能打破终结的执行,因为它可能需要很长的时间和GC不知道他是否只是挂或仍在敲定.