3

I'm Marshalling data across C/C# boundary. I have the following structure:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Message
{
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
   public string From;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
   public string Subject;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
   public string Body;
}

The callback is defined as follows:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void MessageReceiveDelegate([In]IntPtr ptrToMessage);

private void MessageReceiveCallback(IntPtr ptrToMessage)
{
    Message message = (Message)Marshal.PtrToStructure(ptrToMessage, typeof(Message));

    Marshal.FreeHGlobal(ptrToMessage); //This throws COMException!
}

My question is, do I need to worry about releasing IntPtr (ptrToMessage) inside the callback to avoid memory leaks? I tried calling FreeHGlobal on it, but end up with the following exception:

An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll

Additional information: The handle is invalid. (Exception from HRESULT: 0x80070006 (E_HANDLE))

So I'm either doing something wrong, or the memory doesn't need to be released by me.

Eternal21
  • 4,190
  • 2
  • 48
  • 63
  • 2
    If your code is not the owner of the `Intptr` (i.e., did not allocate it) then you should not release it unless the API documents you should. It's also possible you need to use a different `Marshal` method to free the buffer such as `Marshal.FreeCoTaskMem` – GreatAndPowerfulOz Jul 19 '16 at 17:16
  • @Great.And.Powerful.Oz I did not allocate the IntPtr. It's being passed to me from the 3rd party library. I did try using FreeCoTaskMem before, but that caused a crash, instead of just an exception. – Eternal21 Jul 19 '16 at 17:32

1 Answers1

3

This memory was allocated by you? If so - yes, most likely you will have to release it by yourself. If no...

What the API do you use? Does it states that you have to release that memory? What the allocator was used? Does it define a way to release that memory? If so - yes, you have to release it. If no...

No, you should not release it. For example, it could be just a pointer to structure allocated on stack.

If you have a pointer it does not mean it is a dynamically allocated memory.

lorond
  • 3,856
  • 2
  • 37
  • 52