简体   繁体   English

Array.Resize 是否删除旧数组?

[英]Does Array.Resize Delete the old array?

I want to know if Array.Resize deletes the old allocated Array , and if yes when?我想知道Array.Resize删除旧分配的Array ,如果是,什么时候?

I assumed that it deletes it as soon as the values are copied.我认为它会在复制值后立即删除它。
But my teacher says that it only does so at the end of the program, meaning that the memory could be full with the old allocated values.但是我的老师说它只在程序结束时这样做,这意味着内存可能会被旧的分配值填满。
Is that so?是这样吗?

The old Array is not used in my code after the resize, this should call the GC, shouldn't it?调整大小后,我的代码中未使用旧Array ,这应该调用 GC,不是吗?

When objects are garbage-collected is a nondeterministic process and you shouldn't care for that too much.当对象被垃圾收集时是一个不确定的过程,你不应该太在意。

However what is deterministic is when the array is eligible for GC.然而什么确定的是,当阵列可享有GC。 This is when it gets out of scope, or more specific, when there are no more references to it.这是当它超出范围时,或更具体地说,当没有更多引用时。 This happens for example when you're outside the method that contains the array.例如,当您在包含数组的方法之外时,就会发生这种情况。 Being marked for GC however won't delete it, there needs to be some memory pressure on the GC which will make the GC clean up resources.被标记为 GC 但不会删除它,GC 需要有一些内存压力,这将使 GC 清理资源。

HimBromBeere and erikallen already explained what happens. HimBromBeere 和 erikallen 已经解释了发生的事情。 We can also easily verify this experimentally.我们也可以很容易地通过实验验证这一点。

Consider the following code:考虑以下代码:

static void Main(string[] args)
{
    byte[] a = new byte[] { };
    long total = 0;

    Console.WriteLine("Iteration | curent array size (KB) | total allocations (KB) | private memory size (KB)");

    for (int i = 1; i < Int32.MaxValue; i++ )
    {
        Array.Resize(ref a, i);
        total += i;

        if (i % 10000 == 0)
        {
            Console.WriteLine(i.ToString().PadLeft(9) +
                (i / 1024).ToString().PadLeft(25) +
                (total / 1024).ToString().PadLeft(25) +
                (Process.GetCurrentProcess().PrivateMemorySize64 / 1024).ToString().PadLeft(27));
        }
    }
}

which yields the following result:产生以下结果:

Iteration | curent array size (KB) | total allocations (KB) | private memory size (KB)
    10000                        9                    48833                      10560
    20000                       19                   195322                      10924
    30000                       29                   439467                      10976
    40000                       39                   781269                      11040
    50000                       48                  1220727                      11040
    60000                       58                  1757841                      11056
    70000                       68                  2392612                      11080
    80000                       78                  3125039                      11144
    90000                       87                  3955122                      14192
    ...

If all old arrays were kept im memory, we'd need around 4 GB (column total allocations ) after 90000 iterations , but memory usage stays at a low 14 MB (column private memory size ).如果所有旧数组都保留在内存中,则在 90000 次迭代后我们需要大约 4 GB(列total allocations ),但内存使用量保持在 14 MB(列private memory size )的低水平。

旧数组将被 GC 视为无法访问,并将在某个未指定的时间点被释放,就像所有其他对象变得无法访问一样。

An object is elegible for collection when the GC determines that the object is not reachable anymore.当 GC 确定该对象不再可达时,该对象就可以被回收。 Therefore, the original array can be collected if there is no "usable* reference left to reach it.因此,如果没有剩余的“可用*引用”可以到达原始数组,则可以收集原始数组。

When the GC decides to collect the object itself is an alltogether different matter and it is up to the GC to decide;GC 决定收集对象本身是另一回事,由 GC 决定; it might very well not collect it at all during the whole lifetime of your app simply because there is no memory pressure that requires it.它很可能在你的应用程序的整个生命周期内根本不会收集它,因为没有内存压力需要它。

Example:例子:

private Blah[] Frob()
{
    var someArray = new Blah[] { .... }
    //somework
    return (Blah[])Array.Resive(someArray, size);
}

In this case, the object referenced by someArray will be eligible for collection once Frob returns, because the array is no longer reachable.在这种情况下,引用的对象someArray将有资格领取一次Frob的回报,因为数组不再可达。 Its a locally initialized object that can not be reached in any way.它是一个无法以任何方式访问的本地初始化对象。

However, in this example:但是,在这个例子中:

private Frob[] Foo()
{
    var someArray = GetArrayOfFrobs()
    //somework
    return (Blah[])Array.Resive(someArray, size);
}

The object referenced by someArray will be eligible for collection depending on what GetArrayOfFrobs acutally does. someArray引用的对象将符合收集条件,具体取决于GetArrayOfFrobs执行的操作。 If GetArrayOfFrobs returns an array that is cached somewhere or its part of the state of some other reachable object, then the GC will not mark it as collectible.如果GetArrayOfFrobs返回一个缓存在某处的数组或其某个其他可访问对象的状态的一部分,则 GC 不会将其标记为可收集的。

In any case, in a managed environment like .NET it's not methods who decide if a managed object is “freed” or not as you seem to believe based on your question;在任何情况下,在像 .NET 这样的托管环境中,决定托管对象是否被“释放”的方法并不是您根据您的问题似乎相信的; it's the GC and it does a pretty good job, so don't fret about it.它是 GC,它做得很好,所以不要担心。

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

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