0

I have large class which in many places I need to convert array to intPtr

IntPtr convertToIntPtr(Array input)
{
    if (input != null)
    {
        int s = Marshal.SizeOf(input.GetValue(0).GetType()) * input.Length;
        System.IntPtr p = Marshal.AllocHGlobal(s);

        return p;
    }
    return new IntPtr();
}

I know each pointer can be freed using Marshal.FreeHGlobal(IntPtr).

my question is : - will garbagecollector free intptr once used - If no how can I free all of them in close or dispose of class , any event to use such that when intpntr no far used to be deleted

AMH
  • 6,363
  • 27
  • 84
  • 135
  • Why do you need unmanaged memory? Perhaps you don't – David Heffernan Feb 28 '15 at 07:39
  • 1
    Wrap it, derive a class from [SafeBuffer](https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safebuffer%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396). Like [this](http://referencesource.microsoft.com/#mscorlib/microsoft/win32/safehandles/safelocalallochandle.cs,900b817ed497b87b). – Hans Passant Feb 28 '15 at 07:40
  • @DavidHeffernan unfortunatelly I use 3D Dlls which need intptr – AMH Feb 28 '15 at 09:23
  • Not necessarily. Only if they take references to your data. Perhaps you just need to pass `double[]`. – David Heffernan Feb 28 '15 at 09:30

2 Answers2

1

No, the memory you allocate is non-GC handled memory, so it won't be freed (technically it will be freed when your program ends... But I don't think it's what you want).

What you can do is incapsulate the IntPtr in a disposable object.

public sealed class ArrayToIntPtr : IDisposable
{
    public IntPtr Ptr { get; protected set; }

    public ArrayToIntPtr(Array input)
    {
        if (input != null)
        {
            int s = Marshal.SizeOf(input.GetValue(0).GetType()) * input.Length;
            Ptr = Marshal.AllocHGlobal(s);
        }
        else
        {
            Ptr = IntPtr.Zero;
        }
    }

    ~ArrayToIntPtr()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
    }

    protected void Dispose(bool disposing)
    {
        if (Ptr != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(Ptr);
            Ptr = IntPtr.Zero;
        }

        if (disposing)
        {
            GC.SuppressFinalize(this);
        }
    }
}

(note that the class is sealed, so the Dispose(bool disposing) isn't virtual)

xanatos
  • 109,618
  • 12
  • 197
  • 280
0

No, the garbage collector will not free an IntPtr automatically. It's up to you to manage that yourself. I would suggest avoiding doing that as much as possible, but when you need to do that, you should implement the dispose pattern.

Erik
  • 5,355
  • 25
  • 39