{"record":{"id":"de154450042f28b0","repo":"stride3d/stride","slug":"the-memory-pointer-is-invalid-memory-must-have-been","errorCode":null,"errorMessage":"The memory pointer is invalid. Memory must have been allocated with MemoryUtilities.Allocate","messagePattern":"The memory pointer is invalid\\. Memory must have been allocated with MemoryUtilities\\.Allocate","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core/ObjectCollector.cs","lineNumber":66,"sourceCode":"    /// <summary>\n    ///   Adds an object implementing the <see cref=\"IDisposable\"/> or <see cref=\"IReferencable\"/> interfaces,\n    ///   or a <see cref=\"IntPtr\"/> to an object allocated using <see cref=\"MemoryUtilities.Allocate\"/>\n    ///   to the list of the objects to dispose.\n    /// </summary>\n    /// <typeparam name=\"T\">The type of the object to add.</typeparam>\n    /// <param name=\"objectToDispose\">The object to add to the collector to be disposed at a later time.</param>\n    /// <exception cref=\"ArgumentException\">\n    ///   <paramref name=\"objectToDispose\"/> does not implement the interface <see cref=\"IDisposable\"/>, <see cref=\"IReferencable\"/>,\n    ///   and is not a valid memory pointer allocated by <see cref=\"MemoryUtilities.Allocate\"/>.\n    /// </exception>\n    public T Add<T>(T objectToDispose) where T : notnull\n    {\n        if (objectToDispose is not (IDisposable or IReferencable or IntPtr))\n            throw new ArgumentException(\"The object must be IDisposable, IReferenceable, or IntPtr\", nameof(objectToDispose));\n\n        // Check memory alignment\n        if (objectToDispose is IntPtr memoryPtr && !MemoryUtilities.IsAligned(memoryPtr))\n            throw new ArgumentException(\"The memory pointer is invalid. Memory must have been allocated with MemoryUtilities.Allocate\", nameof(objectToDispose));\n\n        EnsureValid();\n\n        if (!disposables.Contains(objectToDispose))\n            disposables.Add(objectToDispose);\n\n        return objectToDispose;\n    }\n\n    /// <summary>\n    ///   Removes a disposable object from the list of the objects to dispose.\n    /// </summary>\n    /// <typeparam name=\"T\">The type of the object to remove.</typeparam>\n    /// <param name=\"objectToDispose\">The object to be removed from the list of objects to dispose.</param>\n    public readonly void Remove<T>(T objectToDispose) where T : notnull\n    {\n        disposables?.Remove(objectToDispose);\n    }","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core/ObjectCollector.cs#L48-L84","documentation":"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.","triggerScenarios":"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).","commonSituations":"Mixing native allocators; passing an uninitialized IntPtr field; wrapping pointers returned by third-party C libraries; off-by-N pointer arithmetic that breaks alignment.","solutions":["Allocate the memory with MemoryUtilities.Allocate before registering the pointer.","Wrap foreign pointers in an IDisposable that frees them with the matching allocator, and register that wrapper instead.","Check alignment with MemoryUtilities.IsAligned(ptr) before adding.","Do not add IntPtr.Zero or unmanaged-by-Stride pointers to the collector."],"exampleFix":"// before\nvar ptr = Marshal.AllocHGlobal(size);\ncollector.Add(ptr); // throws\n// after\nvar ptr = MemoryUtilities.Allocate(size);\ncollector.Add(ptr);","handlingStrategy":"validation","validationCode":"if (!MemoryUtilities.IsAligned(ptr))\n    throw new InvalidOperationException(\"Pointer was not allocated with MemoryUtilities.Allocate\");","typeGuard":null,"tryCatchPattern":"try { collector.Add(ptr); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"MemoryUtilities.Allocate\"))\n{\n    // ptr came from a foreign allocator; free it with the matching API instead\n}","preventionTips":["Always allocate memory you hand to ObjectCollector via MemoryUtilities.Allocate.","Never register IntPtr.Zero or pointers from Marshal/native APIs.","Wrap foreign pointers in a small IDisposable adapter instead."],"tags":["argument-exception","native-memory","alignment","object-collector"],"backgroundTag":"invalid-argument-value","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}