3

I want to know if Array.Resize deletes the old allocated Array, and if yes when?

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?

1
  • @Heinzi Yes I meant the GC, I fixed it. Commented Sep 16, 2020 at 10:41

4 Answers 4

3

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. 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.

Sign up to request clarification or add additional context in comments.

1 Comment

when it gets out of scope That is not true. A variable name can be out of scope, but that doesnt necessarily mean anything to the object's lifetime; it depends on wether the object is reachable which is not the same concept as scope.
2

HimBromBeere and erikallen already explained what happens. 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).

Comments

1

The old array will be considered unreachable by the GC and will be freed at some unspecified point in time, just as all other objects that become unreachable.

Comments

1

An object is elegible for collection when the GC determines that the object is not reachable anymore. 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; 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 bysomeArray will be eligible for collection once Frob returns, because the array is no longer reachable. 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. 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.

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; it’s the GC and it does a pretty good job, so don’t fret about it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.