The golden rule is that you must deallocate from the same heap that was used to allocate the memory.
If you allocate it with malloc()
, you must deallocate it with the free()
from the same C RTL. And likewise on the managed side, AllocHGlobal()
should be balanced by FreeHGlobal()
.
Now, AllocHGlobal()
is implemented by calling the Win32 function LocalAlloc
. So you could free such memory with a call to LocalFree
on the native side. And vice versa.
If you want to use a heap that is shared between native and managed, it is more common to use the COM heap. On the native side use CoTaskMemAlloc()
and CoTaskMemFree()
. On the managed side use Marshal.AllocCoTaskMem()
and Marshal.FreeCoTaskMem()
.
However, you should avoid designing the system like this. It is much simpler to stick to a rule that all memory allocated in the managed side is deallocated there, and likewise for the native side. If you don't follow that rule you will likely soon lose track of who is responsible for what.