NativeList safety handles throwing unexpectedly with Temp allocation.

This code example is simple and shows, what I feel like, is unintended behavior.

[Test]
public void ListTempBug()
{
    NativeList<int> intList1 = new NativeList<int>(Allocator.Temp);
    intList1.Add(0);
    intList1.Add(1);
    intList1.Add(2);
   
    NativeList<int> intList2 = new NativeList<int>(Allocator.Temp);
    intList2.Add(0);
    intList2.Add(1);

    NativeArray<int> intArray2 = intList2.AsArray();
   
    // This line here invalidates the safety handle of intArray2
    intList1.Add(2);

    // System.InvalidOperationException : The NativeArray has been deallocated, it is not allowed to access it
    Debug.Log(intArray2[0]);

    intList1.Dispose();
    intList2.Dispose();
}

I’m guessing that they both use the temp safety handle so changing list1 invalidates the secondary handle (since it’s an array) of list2. I get that knowing how safety handles work but that feels like pretty unexpected behavior using the APIs.

if you change AsArray() to ToArray() than i think it will create a new Native allocation and the exception should not be thrown
(if thats the problem at all)

intList1.Add(2);

is adding to the list. The list could hit capacity, allocated a new chunk of memory for itself and mem copy the existing data to it then deallocate the old memory.

intList2.AsArray(); points to the old memory
ToArray will make a copy of this memory.

__

general rule of thumb for c# if things are named correctly.

To - makes a copy
As - points to existing

2 Likes

He is calling AsArray on intList2 and adding a new item to intList1.

[ ]'s

you make a very good point

Yes doing ToArray() would solve the problem but that’s not really the point. The point this error is just kinda confusing that it happens at all (it happens cause all temp allocations share the same safety handle).

Also a lot of times I don’t want to copy an array and just work in memory so I’m not really happy with the ToArray solution anyways.

And yea, these are two different arrays. I’m not adding to a list of something I AsArrayed previously. This is purely a AtomicSafetyHandle issue, not a memory issue.

Same issue here.

It is a bug for sure…

My walk around now is to use and pass the NativeList instead of the NativeArray return by AsArray. And call AsArray() again after any NativeList operation. Even these operations are on an irrelevant NativeList.
Or simply call AsArray whenever you want to use the List as Array. just don’t keep the return NativeArray as a variable.