HandyOrg/HandyControl · error

StatusException(InteropMethods.Gdip.OutOfMemory)

Error message

StatusException(InteropMethods.Gdip.OutOfMemory)

What it means

This is a GDI+ StatusException wrapping the OutOfMemory status code, thrown when Marshal.AllocHGlobal fails to allocate unmanaged memory for the frame-dimension GUID buffer. The library throws it because the native allocation returned IntPtr.Zero and proceeding would corrupt the native call. Note: GDI+'s OutOfMemory status often means a generic internal failure, not literally insufficient RAM.

Solutions

  1. Validate the GIF file loads correctly (e.g. open it with a known-good decoder) before feeding it to GifImage
  2. Catch OutOfMemoryException/StatusException around GifImage construction and fall back to a static frame
  3. Run the process as 64-bit or reduce concurrent image allocations to relieve address-space pressure
  4. Dispose GifImage promptly (it holds a native handle) to avoid leaked unmanaged memory

Example fix

// before
var gif = new GifImage(stream);
// after
GifImage gif = null;
try { gif = new GifImage(stream); }
catch (Exception ex) when (ex is OutOfMemoryException || ex.Source != null && ex.Message.Contains("OutOfMemory"))
{ /* fall back to static rendering */ }
Defensive patterns

Strategy: try-catch

Validate before calling

if (buffer == IntPtr.Zero || count <= 0) { /* skip native call, use fallback */ }

Type guard

static bool IsUsableGifStream(Stream s) => s != null && s.CanRead && s.Length > 6;

Try / catch

try { var gif = new GifImage(stream); }
catch (OutOfMemoryException) { /* static fallback frame */ }

Prevention

When it happens

Trigger: Calling into GifImage frame-dimension enumeration (e.g. during initialization or EnsureSave/CanAnimate paths) when AllocHGlobal(checked(size*count)) cannot secure the requested unmanaged block — typically a huge or corrupt frame-dimension count read from a malformed GIF.

Common situations: Corrupt or truncated GIF files that report an absurd frame dimension count; memory pressure in the process (32-bit address space exhaustion); running after the native GDI+ handle has gone bad.

Related errors


AI-assisted analysis of HandyOrg/HandyControl@2c0875ebd6 (2026-09-14). Data as JSON: /api/errors/f44eb3da50af1b2e. Report an issue: GitHub.

Appendix: source

Thrown at src/Shared/HandyControl_Shared/Controls/Image/GifImage.cs:366

        {
            var status = InteropMethods.Gdip.GdipImageGetFrameDimensionsCount(new HandleRef(this, NativeImage), out var count);

            if (status != InteropMethods.Gdip.Ok)
            {
                throw InteropMethods.Gdip.StatusException(status);
            }

            if (count <= 0)
            {
                return new Guid[0];
            }

            var size = Marshal.SizeOf(typeof(Guid));

            var buffer = Marshal.AllocHGlobal(checked(size * count));
            if (buffer == IntPtr.Zero)
            {
                throw InteropMethods.Gdip.StatusException(InteropMethods.Gdip.OutOfMemory);
            }

            status = InteropMethods.Gdip.GdipImageGetFrameDimensionsList(new HandleRef(this, NativeImage), buffer, count);

            if (status != InteropMethods.Gdip.Ok)
            {
                Marshal.FreeHGlobal(buffer);
                throw InteropMethods.Gdip.StatusException(status);
            }

            var guids = new Guid[count];

            try
            {
                for (var i = 0; i < count; i++)
                {
                    guids[i] = (Guid) InteropMethods.PtrToStructure((IntPtr) ((long) buffer + size * i), typeof(Guid));
                }

View on GitHub (pinned to 2c0875ebd6)