If I allocate some memory with AllocHGlobal, do I have to free it with FreeHGlobal?
.net, c#, interop, memory
Solution
Yes, C# will not automatically free memory allocated by `Marshal.AllocHGlobal`. That memory must be freed with a call to `Marshal.FreeHGlobal` or else it will be leaked.
You could create something a smart pointer to wrap the `IntPtr`
class StructWrapper : IDisposable {
public IntPtr Ptr { get; private set; }
public StructWrapper(object obj) {
if (Ptr != null) {
Ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj));
Marshal.StructureToPtr(obj, Ptr, false);
}
else {
Ptr = IntPtr.Zero;
}
}
~StructWrapper() {
if (Ptr != IntPtr.Zero) {
Marshal.FreeHGlobal(Ptr);
Ptr = IntPtr.Zero;
}
}
public void Dispose() {
Marshal.FreeHGlobal(Ptr);
Ptr = IntPtr.Zero;
GC.SuppressFinalize(this);
}
public static implicit operator IntPtr(StructWrapper w) {
return w.Ptr;
}
}
Using this wrapper you can either manually free the memory by wrapping the object in a `using` statement or by allowing it to be freed when the finalizer runs.
Problem
I wrote a helper method, ``` internal static IntPtr StructToPtr(object obj) { var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj)); Marshal.StructureToPtr(obj, ptr, false); return ptr; } ``` Which takes a `struct` and gives me back an `IntPtr` to it. I use it as such: ``` public int Copy(Texture texture, Rect srcrect, Rect dstrect) { return SDL.RenderCopy(_ptr, texture._ptr, Util.StructToPtr(srcrect), Util.StructToPtr(dstrect)); } ``` The problem is that I only need that `IntPtr` for a split second so that I can pass it off to the C DLL, ``` [DllImport("SDL2.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_RenderCopy")] internal static extern int RenderCopy(IntPtr renderer, IntPtr texture, IntPtr srcrect, IntPtr dstrect); ``` I don't really want to have to worry about freeing it; otherwise my 1-line function grows to 6: ``` public int Copy(Texture texture, Rect? srcrect=null, Rect? dstrect=null) { var srcptr = Util.StructToPtr(srcrect); var dstptr = Util.StructToPtr(dstrect); var result = SDL.RenderCopy(_ptr, texture._ptr, srcptr, dstptr); Marshal.FreeHGlobal(srcptr); Marshal.FreeHGlobal(dstptr); return result; } ``` Is there a better way to do this? Will C# eventually clean up any memory it has allocated? If not, is there a way I can wrap the call to `SDL.RenderCopy` in some `using` statements instead so that I don't have to do all this temporary variable + explicit freeing non-sense?