C# 为什么这个对象没有被垃圾收集

C# 为什么这个对象没有被垃圾收集,c#,garbage-collection,C#,Garbage Collection,在下面的代码段中,我想知道为什么在函数调用之后没有收集testvectors。我看到内存使用率上升到270Mb,然后一直保持不变 此函数直接从Main调用 private static void increaseMemoryUsage() { List<List<float>> testvectors = new List<List<float>>(); int vectorNum = 250 * 250; Random r

在下面的代码段中,我想知道为什么在函数调用之后没有收集
testvectors
。我看到内存使用率上升到270Mb,然后一直保持不变

此函数直接从Main调用

private static void increaseMemoryUsage()
{
    List<List<float>> testvectors = new List<List<float>>();
    int vectorNum = 250 * 250;
    Random rand = new Random();

    for (int i = 0; i < vectorNum; i++)
    {
        List<Single> vec = new List<Single>();

        for (int j = 0; j < 1000; j++)
                {
            vec.Add((Single)rand.NextDouble());
        }
        testvectors.Add(vec);
    }
}
private static void increaseMemoryUsage()
{
List testvectors=新列表();
int vectorNum=250*250;
Random rand=新的Random();
for(int i=0;i
不要混淆垃圾收集和引用计数。当运行时决定释放内存时,并不总是在不再引用时释放内存。引述:

当满足下列条件之一时,会发生垃圾回收 正确:

系统的物理内存不足

托管堆上已分配对象使用的内存 超过可接受的阈值。这意味着 托管堆上已超过可接受的内存使用率。这 阈值在进程运行时不断调整

调用GC.Collect方法。几乎在所有情况下,您都没有 调用此方法,因为垃圾收集器连续运行。 此方法主要用于特殊情况和测试

如果您感兴趣,请阅读以下内容:


GC可以在需要时运行。那可能要晚很多。在最后一次引用消失后,没有义务直接释放一些内存。您的阵列将在下一个Gen2集合中被收集

除非您继续分配内存,否则函数返回后它可能永远不会运行


您可以使用
GC.Collect()
手动触发GC,但通常不建议这样做。

最有可能的情况是,您的TestVector被提升到大对象堆(LOH),然后在Gen0收集期间不会收集它


很好的链接。

运行此操作时,我观察到相反的情况:

 class Program
    {
        static void Main(string[] args)
        {
            increaseMemoryUsage();

            Console.WriteLine("Hit enter to force GC");
            Console.ReadLine();

            GC.Collect();

            Console.ReadLine();
        }

        private static void increaseMemoryUsage()
        {
            var testvectors = new List<List<float>>();
            const int vectorNum = 250 * 250;
            var rand = new Random();

            for (var i = 0; i < vectorNum; i++)
            {
                var vec = new List<Single>();

                for (var j = 0; j < 1000; j++)
                    vec.Add((Single)rand.NextDouble());

                testvectors.Add(vec);
            }
        }    
    }
类程序
{
静态void Main(字符串[]参数)
{
增加MemoryUsage();
控制台.WriteLine(“按回车键强制GC”);
Console.ReadLine();
GC.Collect();
Console.ReadLine();
}
私有静态无效增量MemoryUsage()
{
var testvectors=新列表();
const int vectorNum=250*250;
var rand=new Random();
对于(var i=0;i
垃圾收集是不确定的。由GC决定什么时候是做这件事的好时机。

尝试在IncreaseMemorySage()方法使用之前和之后添加,并比较数字。

定义“永远”,以及如何检查它?您不能仅仅通过查看RAM消耗来了解GC。请尝试调用GC.collect或其他等效程序,并检查发生了什么。为什么需要收集它?请记住,GC尽可能地懒惰,因为收集总是很昂贵的。仅仅因为一件物品是可以收藏的,并不意味着它会被收藏。它将在GC决定需要释放内存时收集,而不是在之前。另外,请查看您创建vec=new List()的代码,您可以用两种不同的方法更正此问题。。在执行testvectors.Add(ver)之后添加一行vec.clear();vec=null;或将创建的vec移除到for循环的外部。。如果您不希望列表调整大小,那么您也可以执行List vec=new List(1000);例如,与列表testvectors相同=新列表(1000);你明白我为什么建议你的衣服的初始尺寸吗List@Johnyy我怀疑如果你稍微用力一点,然后尝试用大量内存来做其他事情,它会的。让GC在它喜欢的时候运行(而不是用
GC.Collect()
)强制它)几乎总是正确的做法。当一个对象不再被引用时,系统通常比您更清楚地知道如何以及何时回收材料以获得最佳性能,而您强制它只是导致它自我猜测,在许多情况下运行较慢。必须立即回收对象的情况非常罕见。系统的信息比程序员少。例如,它不知道您刚刚删除了对200MB数据的最后一个引用。因此,在这种情况下,手动调用它可能是合理的。不幸的是,没有什么好方法可以告诉GC您不再需要大量内存,而不强制它运行。大概系统对特定对象的信息较少,但总体上信息更多。如果它知道另一个对200MB数据的引用,那么你所做的就是让这些东西在另一个GC中存活下来(并有可能将其推广到下一代)。所以如果你要强迫它,你最好他妈的确定你是对的。是的,GC.collect确实把它搞定了。但是,不鼓励使用GC.collect。。。没错,你不需要参与GC,这是你问题的答案;一旦引用超出范围,内存就不会被回收。我要说的一点是,对象可用于收集,并且将在CLR认为合适时收集。