nativeParallelHashMap disposed several times but IsCreated not detected

There must be a call to the same NativeParallelHashMap twice somewhere in my code base.
It tells me

ObjectDisposedException: Cannot access a disposed object.
Object name: ‘The NativeArray has been disposed, it is not allowed to access it’.

But the object is Disposed() after checking if IsCreated() first.
Seems like IsCreated() is not detecting that disposal.

In the same function, a NativeArray is disposed correctly. So it’s a problem with the HashMap.

How’s that possible?
Is this a bug?

How do you dispose a hash map correctly then?

IsCteated only checks the status of the local struct instance representing the collection, and won’t detect disposal of the collection from another instance of the struct elsewhere in memory. Say you have the below

NativeList<int> a=…;
var b = a;
b.Dispose();

The one underlying collection referenced by both a and b has been disposed. Variable b now has its internal reference cleared. Variable a, on the other hand, still points to the place where the collection (UnsafeList) used to be. a.IsCreated is true, b.IsCreated is false. You just generally need to be careful about creation / disposal / value-copying collections.

Could you show your code? Are you reusing this hashmap variable?

Code is private and too big to show, but basically is an internal native hash map used exclusively inside a class, not output. And there’s only ONE call to Dispose() with an IsCreated() test before. Weird but seems like it passes through. This class has several instances of it created…

Thanks! But it’s not the case. It is placed inside a class, it’s not output or assigned to anything else, and there’s a bunch of instsances of it and the only way to dispose it is to call

Dispose() , which calls IsCreated() first. And it still fails… I’ll try to think a little bit about it.

Also note that there’s two calls to dispose() in there. One for the hashmap , one for a native array. If I swap those in order, then I get a call of a job that has not been completed somewhere else. Could that be related to the way the HashMap works? maybe that’s the real error and hashmaps are not working well after getting that error?

Details on Unity / collections package versions would be useful.

Some code patterns create [defensive] copies of value types. The ones most applicable here would be using a property or a readonly field for the collection, both of which would prevent a direct Dispose call from affecting the state of the class member. The appropriate way to store a collection is therefore a normal mutable field, or perhaps a ref property if necessary. In these cases, you would only ever be mutating one instance of the struct in memory, and Dispose calls will be idempotent as intended.

There may be multiple calls to whatever in your class disposes the collections. You could create logic to early out if the disposal code has already run previously. That would be a bit of a band-aid, though, and it would be better to address the root cause.

The error for the hash map is almost certainly due to a previous disposal, since the error message is only used when the safety handle of the collection was invalidated. If the error when swapping the order occurs when disposing the array, that is probably an issue with the array’s usage in jobs somewhere.

It really is much easier to diagnose things with a concrete repro. Help us help you by cutting down the stuff into the minimum complete code needed to reproduce the issue.