Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

NativeList safety handles throwing unexpectedly with Temp allocation.

Discussion in 'Entity Component System' started by cjddmut, Jan 15, 2020.

  1. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    177
    This code example is simple and shows, what I feel like, is unintended behavior.

    Code (CSharp):
    1. [Test]
    2. public void ListTempBug()
    3. {
    4.     NativeList<int> intList1 = new NativeList<int>(Allocator.Temp);
    5.     intList1.Add(0);
    6.     intList1.Add(1);
    7.     intList1.Add(2);
    8.    
    9.     NativeList<int> intList2 = new NativeList<int>(Allocator.Temp);
    10.     intList2.Add(0);
    11.     intList2.Add(1);
    12.  
    13.     NativeArray<int> intArray2 = intList2.AsArray();
    14.    
    15.     // This line here invalidates the safety handle of intArray2
    16.     intList1.Add(2);
    17.  
    18.     // System.InvalidOperationException : The NativeArray has been deallocated, it is not allowed to access it
    19.     Debug.Log(intArray2[0]);
    20.  
    21.     intList1.Dispose();
    22.     intList2.Dispose();
    23. }
    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.
     
  2. Flipps

    Flipps

    Joined:
    Jul 30, 2019
    Posts:
    51
    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)
     
  3. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    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
     
    RoughSpaghetti3211 and Flipps like this.
  4. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    138
    He is calling AsArray on intList2 and adding a new item to intList1.

    []'s
     
  5. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    you make a very good point
     
  6. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    177
    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.
     
    Last edited: Jan 16, 2020
  7. Lieene-Guo

    Lieene-Guo

    Joined:
    Aug 20, 2013
    Posts:
    547
  8. Lieene-Guo

    Lieene-Guo

    Joined:
    Aug 20, 2013
    Posts:
    547
    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.