stride3d/stride · error · ArgumentException

The memory pointer is invalid. Memory must have been…

Error message

The memory pointer is invalid. Memory must have been allocated with MemoryUtilities.Allocate

What it means

When an IntPtr is added to ObjectCollector, it is treated as a native memory block that must be freed later, so it must have been produced by MemoryUtilities.Allocate (which guarantees the alignment IsAligned checks). A pointer from malloc/new/stack memory or an arbitrary address fails this check and throws ArgumentException, because releasing it through Stride's allocator would corrupt the heap.

Solutions

  1. Allocate the memory with MemoryUtilities.Allocate before registering the pointer.
  2. Wrap foreign pointers in an IDisposable that frees them with the matching allocator, and register that wrapper instead.
  3. Check alignment with MemoryUtilities.IsAligned(ptr) before adding.
  4. Do not add IntPtr.Zero or unmanaged-by-Stride pointers to the collector.

Example fix

// before
var ptr = Marshal.AllocHGlobal(size);
collector.Add(ptr); // throws
// after
var ptr = MemoryUtilities.Allocate(size);
collector.Add(ptr);
Defensive patterns

Strategy: validation

Validate before calling

if (!MemoryUtilities.IsAligned(ptr))
    throw new InvalidOperationException("Pointer was not allocated with MemoryUtilities.Allocate");

Try / catch

try { collector.Add(ptr); }
catch (ArgumentException ex) when (ex.Message.Contains("MemoryUtilities.Allocate"))
{
    // ptr came from a foreign allocator; free it with the matching API instead
}

Prevention

When it happens

Trigger: Calling collector.Add(intPtr) where intPtr was obtained from anything other than MemoryUtilities.Allocate (e.g. Marshal.AllocHGlobal, native library return values, a default/zero IntPtr that is misaligned).

Common situations: Mixing native allocators; passing an uninitialized IntPtr field; wrapping pointers returned by third-party C libraries; off-by-N pointer arithmetic that breaks alignment.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/de154450042f28b0. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core/ObjectCollector.cs:66

    /// <summary>
    ///   Adds an object implementing the <see cref="IDisposable"/> or <see cref="IReferencable"/> interfaces,
    ///   or a <see cref="IntPtr"/> to an object allocated using <see cref="MemoryUtilities.Allocate"/>
    ///   to the list of the objects to dispose.
    /// </summary>
    /// <typeparam name="T">The type of the object to add.</typeparam>
    /// <param name="objectToDispose">The object to add to the collector to be disposed at a later time.</param>
    /// <exception cref="ArgumentException">
    ///   <paramref name="objectToDispose"/> does not implement the interface <see cref="IDisposable"/>, <see cref="IReferencable"/>,
    ///   and is not a valid memory pointer allocated by <see cref="MemoryUtilities.Allocate"/>.
    /// </exception>
    public T Add<T>(T objectToDispose) where T : notnull
    {
        if (objectToDispose is not (IDisposable or IReferencable or IntPtr))
            throw new ArgumentException("The object must be IDisposable, IReferenceable, or IntPtr", nameof(objectToDispose));

        // Check memory alignment
        if (objectToDispose is IntPtr memoryPtr && !MemoryUtilities.IsAligned(memoryPtr))
            throw new ArgumentException("The memory pointer is invalid. Memory must have been allocated with MemoryUtilities.Allocate", nameof(objectToDispose));

        EnsureValid();

        if (!disposables.Contains(objectToDispose))
            disposables.Add(objectToDispose);

        return objectToDispose;
    }

    /// <summary>
    ///   Removes a disposable object from the list of the objects to dispose.
    /// </summary>
    /// <typeparam name="T">The type of the object to remove.</typeparam>
    /// <param name="objectToDispose">The object to be removed from the list of objects to dispose.</param>
    public readonly void Remove<T>(T objectToDispose) where T : notnull
    {
        disposables?.Remove(objectToDispose);
    }

View on GitHub (pinned to 96fad776d2)