Crash when sorting NativeList.

Hi,

Any idea of what can be causing this error:
NullReferenceException: Object reference not set to an instance of an object
System.Buffer.memcpy4 (System.Byte* dest, System.Byte* src, System.Int32 size) (at <437ba245d8404784b9fbab9b439ac908>:0)
System.Buffer.Memcpy (System.Byte* dest, System.Byte* src, System.Int32 size) (at <437ba245d8404784b9fbab9b439ac908>:0)
System.String.memcpy (System.Byte* dest, System.Byte* src, System.Int32 size) (at <437ba245d8404784b9fbab9b439ac908>:0)
Unity.Collections.LowLevel.Unsafe.UnsafeUtility.ReadArrayElement[T] (System.Void* source, System.Int32 index) (at <7d22f8e71133418c87c7b26ea181f3e3>:0)
Unity.Collections.NativeSortExtension.Partition[T,U] (System.Void* array, System.Int32 lo, System.Int32 hi, U comp) (at Library/PackageCache/com.unity.collections@0.1.1-preview/Unity.Collections/NativeSort.cs:142)

It’s weird because the code runs up to the first of these lines but crashes on the secons:

while (comp.Compare(pivot, UnsafeUtility.ReadArrayElement(array, ++left)) > 0) ;
while (comp.Compare(pivot, UnsafeUtility.ReadArrayElement(array, --right)) < 0) ;

The function where it crashes is
unsafe static int Partition<T, U>(void* array, int lo, int hi, U comp) where T : struct where U : IComparer
of class NativeSortExtension.

I’m sorting a NativeList:

var array = new NativeList<SpatialRender>(Allocator.TempJob);

And sorting by calling sort function on the array:

array.Sort(comparer);

Where SpatialRender is a struct:

public struct SpatialRender
{
    public float3 location;
    public int renderDataIndex;
    public Matrix4x4 matrix;
    public Vector4 frame;
}

and comparer is a struct of type:

protected struct LocationComparer : IComparer<SpatialRender>
{
    public int Compare(SpatialRender a, SpatialRender b)
    {
        if (a.location.y < b.location.y)
            return 1;
        else
            return -1;
    }
}

On Unity 2019.3.0f5
Entities preview.17 - 0.5.0
Collections preview.9 - 0.5.0
Burst 1.2.1

Thanks.

Hello,

I made a test like this:

        var list = new NativeList<SpatialRender>(Allocator.TempJob) 
        { 
            new SpatialRender{location = new float3(0, 7, 0)},
            new SpatialRender{location = new float3(0, 2, 0)},
            new SpatialRender{location = new float3(0, 5, 0)},
            new SpatialRender{location = new float3(0, 4, 0)},
            new SpatialRender{location = new float3(0, 8, 0)},
            new SpatialRender{location = new float3(0, 3, 0)},
            new SpatialRender{location = new float3(0, 6, 0)},
            new SpatialRender{location = new float3(0, 12, 0)},
            new SpatialRender{location = new float3(0, 11, 0)},
            new SpatialRender{location = new float3(0, 11, 0)}
        };

        new TestJob { list = list }.Schedule().Complete();
        for (int i = 0; i < list.Length; i++)
        {
            var item = list[i];
            Debug.Log(item.location.y);
        }
        list.Dispose();
    [Unity.Burst.BurstCompile]
    public struct TestJob : IJob
    {
        public NativeList<SpatialRender> list;

        public void Execute()
        {
            list.Sort(new LocationComparer());
        }
    }

and it works fine (i am running this code in a monobehaviour), it properly sorts on descending order, maybe if you can give us more information about your code perhaps people can help you better.

Thanks.

The code is a bit long.

  1. I generate a tile map with a Diamond-Square algorithm, with only two types of terrain.
  2. I generate data for trees where the value of the tile is less that 0.5 with some ramdomness. Only one tree per tile.
  3. I inject the trees data into the static NativeHashMap m_spatialPartitionRenderStatics of the system JSystemSpatialPartition.
  4. In the system JSystemSpatialPartition I fill the NativeMultiHashMap m_spatialPartitionRender with the render data of all entities in screen, including the trees.
  5. In the system JSystemPrerender I sort the data of m_spatialPartitionRender and prepare it for render:
  6. Get all the unique keys of JSystemSpatialPartition.m_spatialPartitionRender and sort them
  7. Loop those keys, get the values of those keys and add them to as many NativeList as I need to mantain the sort time low.
  8. Sort each NativeList (here is when randomly crashes).
  9. Fill a NativeArray, a NativeArray and a NativeList with limits up to 1023, that are going to be used for render with Graphics.DrawMeshInstanced by the system SystemSpritesRenderer.

The crash is random, always sorting a NativeList (step 8), and I have not been able to reproduce it when I don’t add the trees render data to m_spatialPartitionRender in the system JSystemSpatialPartition. This does not mean that the trees are the cause, only, for now, that they increase the probability of the crash.

This is my first experment with DOTS so it’s a bit difficult for me to trace the cause of this bug. Maybe is a memory leak. maybe some data is being overwritten.

Any advise?

Thanks again.

Change

protected struct LocationComparer : IComparer<SpatialRender>
{
    public int Compare(SpatialRender a, SpatialRender b)
    {
        if (a.location.y < b.location.y)
            return 1;
        else
            return -1;
    }
}

to

protected struct LocationComparer : IComparer<SpatialRender>
{
    public int Compare(SpatialRender a, SpatialRender b)
    {
        if (a.location.y < b.location.y)
            return 1;
        else if (a.location.y > b.location.y)
            return -1;
        else
            return 0;
    }
}

I had the same issue.

Cheers.

2 Likes

Wow, I missed it, I’ll try it.

thanks!!!

This fixed my issue.

Thanks

2 Likes

This thread saved my day!
Thanks a lot.

Cheers :wink:

2 Likes

recently had same issue

just using IComparer that have logic mistake in condition makes Sort() going out of array bounds without any warning/error at all, even with ENABLE_UNITY_COLLECTIONS_CHECKS

debugging such thing is a nightmare, Sort() should perform array bounds check at least in editor with define above