Freeing memory in 2d arrays

MPIon

Well-known member
Joined
Jun 13, 2020
Messages
73
Location
England
Programming Experience
10+
I have a 2d array defined in the form :-
C#:
static byte[][] blockData = new byte[1000][];

The second dimension is created as follows :-
C#:
blockData[i] = new byte[<block size>];

Periodically due to memory issues, I need to clear a block and allocate a new one, so I was using
C#:
blockData[i] = null;
(hoping the garbage collector would free the memory.

This does work, but moving a project from Net FrameWork to Net 7, I am getting warnings on the blockData = null line -
Cannot convert null literal to non-nullable reference type.
(there are no such warnings in the Net FrameWork version).

I don't like warnings in my code, so presumably I am not doing something quite right. Perhaps I don't need to set the blockData to null at all and the grabage collector will automatically clear the memory when I assign a new block to it?
 
Read:
and:
 
Read:
and:

Skydiver,

Thanks for the reply and I am working my way through the documents to make sure I have a full understanding of all this.

However, I have several points.
Firstly, I think (just my opinion), the term Dereference is a confusing term and not very good English. It does not mean what someone reading it might think it means. In the c# context it means accessing the variable behind the reference. In c or c++ that would be accessing the variable that is pointed to by another variable (as in *pointer).

In my example, when the array is first created, the second dimension has not been allocated, so is clearly null (and must therefore be a nullable type), so I am still not clear why resetting it to null should cause a warning.

Secondly, this only addresses half the issue I have, which is more about the memory allocation itself, i.e. does setting the value to null enable the memory to be released.
 
It's worth noting that you do not have a 2D array. Terminology is important to avoid confusion - both ours and yours. What you have is a jagged array, i.e. an array of arrays. A 2D array uses [,] syntax while a jagged array uses [][] syntax.
 
It's worth noting that you do not have a 2D array. Terminology is important to avoid confusion - both ours and yours. What you have is a jagged array, i.e. an array of arrays. A 2D array uses [,] syntax while a jagged array uses [][] syntax.

Yes, of course you are quite correct. Its a few years since I wrote this code and am having to relearn a lot and figure out why I did something the way I did.
 
In my example, when the array is first created, the second dimension has not been allocated, so is clearly null (and must therefore be a nullable type), so I am still not clear why resetting it to null should cause a warning.

The compiler is trying its best to warn you that something could go wrong by assigning the null. It's not actually preventing you from doing the assignment (unless you switch the compiler mode to treat warnings as errors). C# is not (yet) like Rust which has much stricter guard rails.

If the warning bothers you, turn off nullables, or setup a nullable context.
 
Just don't set it null, set it to the new size you want. You'll only free up memory if the new size is smaller than the old size

there are no such warnings in the Net FrameWork version

Because .net FW doesn't support compile time checking nullable reference types for being null

.net FW will let you do this:

C#:
string name = null;
Console.Write(name.Length);

And it will crash at runtime

nullable checking enabled in .net 7 you get a warning if you try and do

C#:
string name= null;

Because you promised name wouldn't be null (you declared it as `string` thus forging a promise that it wouldn't be null), and then went and set it null

If you promise that name might be null:

C#:
string? name = null;

You then get a warning on the next line:

C#:
Console.Write(name.Length);

Because the compiler can see that name might be null (because it's a `string?`) and you haven't done anything to guard against it being null (test it for null or make a non null assignment recently) before you used it

Point to `name` with your mouse for more info; the tooltip says "name might be null here" - no kidding


All this helps stop you writing code that blows up with NullReferenceException. It's merely like your mom watching over your shoulder and going "erm, you've used that but I can't see you having set it to anything first.."

It's not perfect - there are times you know something won't be null but the compiler can't see it, so you have to override its nagging with a !.. For example, you know your dependency injector/json deserializer etc will set this property up:

C#:
class X{

  public string Y {get;set;}        //json.net deser will not forget to set this to some value

//message "must have been assigned a value before the constructor finishes..."

We need to set some value to stop the warning, and we don't want to construct a useless empty object that will get tossed out, so we can set it null ... But then we get a warning for setting a non-nullable to null so we use ! to silence the warning, and we rest assured we know for sure that it won't be null when the deserializer is finished with it, before we ever get to use it ourselves

C#:
class X{

  public string Y {get;set;} = default!        //json.net deser will not forget to set this to some value

You can apply the ! override on reading the variable too, if you know something the compiler cannot..


C#:
string? x = default;

foreach(var y in z) // z always definitely has at least one value in the collection
  x = y;

//x definitely has a value but the compiler wont know that - it merely thinks 'well the loop may not run, so x may be null'

Console.Write(x!.Length);

Don't just slap ? and ! around trying to get warnings to go away; think about why they're appearing. Nullable context is useful in avoiding the number one cause of .net crashes
 
Last edited:
Back
Top Bottom