stride3d/stride · error · ArgumentException

Pointer cannot be equal to IntPtr.Zero

Error message

Pointer cannot be equal to IntPtr.Zero

What it means

The PixelBuffer constructor requires a non-null native pointer because the buffer is a view over existing pixel memory, never an owner. Passing IntPtr.Zero would produce a buffer whose DataPointer is invalid, so the constructor throws ArgumentException for the dataPointer argument.

Solutions

  1. Check the pointer for IntPtr.Zero before constructing and handle the failed allocation.
  2. Allocate memory with Marshal.AllocHGlobal or obtain a valid pointer from a staging resource before wrapping it.
  3. Use an Image/PixelBuffer factory that allocates internally instead of wrapping raw memory.

Example fix

// before
var pb = new PixelBuffer(w, h, format, rowStride, bufferStride, ptr);
// after
if (ptr == IntPtr.Zero) throw new OutOfMemoryException("pixel allocation failed");
var pb = new PixelBuffer(w, h, format, rowStride, bufferStride, ptr);
Defensive patterns

Strategy: validation

Validate before calling

if (dataPointer == IntPtr.Zero)
    throw new InvalidOperationException("Cannot wrap pixel data: native allocation returned zero");

Type guard

bool HasValidPointer(IntPtr p) => p != IntPtr.Zero;

Try / catch

try { var pb = new PixelBuffer(w, h, fmt, rowStride, bufferStride, ptr); }
catch (ArgumentException ex) when (ex.ParamName == "dataPointer") { log.Error("null pixel data pointer"); throw; }

Prevention

When it happens

Trigger: Calling new PixelBuffer(width, height, format, rowStride, bufferStride, dataPointer) with dataPointer == IntPtr.Zero, typically when a native allocation (e.g. from a GPU staging readback or Marshal.AllocHGlobal) returned zero or was not yet initialized.

Common situations: Interop code where a native allocation failed and returned IntPtr.Zero; calling the constructor before a staging texture readback populated the pointer; mis-ordered init code where the pointer field is still default(IntPtr).

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Foundation/Graphics/PixelBuffer.cs:66

        /// <summary>
        /// True when RowStride == sizeof(pixelformat) * width
        /// </summary>
        private readonly bool isStrictRowStride;

        /// <summary>
        /// Initializes a new instance of the <see cref="PixelBuffer" /> struct.
        /// </summary>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <param name="format">The format.</param>
        /// <param name="rowStride">The row pitch.</param>
        /// <param name="bufferStride">The slice pitch.</param>
        /// <param name="dataPointer">The pixels.</param>
        public PixelBuffer(int width, int height, PixelFormat format, int rowStride, int bufferStride, IntPtr dataPointer)
        {
            if (dataPointer == IntPtr.Zero)
                throw new ArgumentException("Pointer cannot be equal to IntPtr.Zero", "dataPointer");

            this.width = width;
            this.height = height;
            this.format = format;
            this.rowStride = rowStride;
            this.bufferStride = bufferStride;
            this.dataPointer = dataPointer;
            this.pixelSize = format.SizeInBytes;
            this.isStrictRowStride = (pixelSize * width) == rowStride;
        }

        /// <summary>
        /// Gets the width.
        /// </summary>
        /// <value>The width.</value>
        public int Width { get { return width; } }

        /// <summary>

View on GitHub (pinned to 96fad776d2)