Crash when allocating and freeing memory in a C# Job

When repeatedly allocating and deallocating memory in a C# Job (not necessarily using burst) Unity can sometimes crash with a stack trace ending at the DynamicHeapAllocator::Allocate method (though I have seen various stacktraces). This crash is non-deterministic but I can reliably recreate it within one minute usually.

Is allocation in C# jobs actually supported? It seems to be since even the NativeList depends on this.
However these crashes seem to indicate there’s either a bug in my code or there is a bug in Unity’s code.

Below is a code sample that reproduces this. Using an IJobParallelFor is not strictly necessary, however I have found that it triggers the crash much more quickly.

using Unity.Jobs;
using UnityEngine;
using Unity.Mathematics;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs.LowLevel.Unsafe;

public class Repro : MonoBehaviour {
    struct AllocationJob : IJobParallelFor {
        [NativeDisableParallelForRestriction]
        public NativeArray<UnsafeAppendBuffer> buffers;

        [NativeSetThreadIndex]
        private int threadIndex;

        public void Execute(int index) {
            // Safe since we index by thread index
            var tmpBuffer = buffers[threadIndex];
            // Simulate appending to the buffer
            int dummySize = 200;
            if (tmpBuffer.Size + dummySize > tmpBuffer.Capacity) {
                tmpBuffer.SetCapacity(math.max(tmpBuffer.Size + dummySize, tmpBuffer.Capacity * 2));
            }
            tmpBuffer.Size += dummySize;
            // Write back the buffer struct to the array
            buffers[threadIndex] = tmpBuffer;
        }
    }

    public void Update() {
        // Allocate buffers
        var commandBuffers = new NativeArray<UnsafeAppendBuffer>(JobsUtility.MaxJobThreadCount, Allocator.Persistent, NativeArrayOptions.ClearMemory);
        for (int i = 0; i < commandBuffers.Length; i++) commandBuffers[i] = new UnsafeAppendBuffer(0, 4, Allocator.Persistent);

        // Run the job
        new AllocationJob {
            buffers = commandBuffers,
        }.Schedule(100 * 1000, 100).Complete();

        // Free all buffers
        for (int i = 0; i < commandBuffers.Length; i++) {
            var cmd = commandBuffers[i];
            cmd.Dispose();
            commandBuffers[i] = cmd;
        }
        commandBuffers.Dispose();
    }
}

In the script memory is allocated inside an UnsafeAppendBuffer with the Persistent allocator which internally uses Malloc and Free. Every frame a IJobParallelFor job is started which appends to some buffers multiple times. Note that multiple buffers are used and the job writes to the correct buffer depending on the thread index (set using the NativeSetThreadIndex attribute) to avoid different threads writing to the same memory locations. The memory is freed every frame after the job is complete.

I have verified that this happens in a few different versions of Unity 2019.3.

Having the profiler enabled seems to make the crash trigger more often since the profiler also allocates a lot of memory.

Is there anyone who knows if allocation inside C# jobs is definitely supposed to be supported?

1 Like

only with Temp allocator

@M_R
I’m not talking about NativeArrays. They can indeed only be allocated with the Temp allocator. However there is the UnsafeUtility.Malloc method which seems to be supported inside C# jobs. NativeList even uses it.

Anyone?

Gonna try and reproduce the failure today my end.

Awesome! Thank you! Earlier I also submitted a bug report with a sample project. Might be useful for you. The case ID is 1196612.

Could not reproduce my end unfortunately - tried multiple runs with Burst/without Burst, tried restarting the editor like you suggested on the case ID.

That’s both unfortunate and good to hear. That means it is probably supposed to be supported.
Is there a way I could get access to a debug build of Unity or be able to more easily help track it down? Or can I in some other way help debug this?

1 Like