Reputation: 5202
I have codes interop between C# (core) and C++ (unmanaged DLL).
Memory allocated in C# using Marshal.AllocHGlobal()
needs to be released in C# using Marshal.FreeHGlobal()
.
Memory allocated in C++ using new
needs to be released in C++ using delete
.
Can I just delete
or FreeHGlobal()
whenever I wish, since the GC is no longer tracing these memory handler?
Upvotes: 0
Views: 1137
Reputation: 596497
No, you cannot just use whatever method you want to free memory. You MUST use whatever the allocator requires you to use. Only the memory manager that allocates a given block of memory knows how to free that block of memory properly.
For instance, the documentation for Marshal.AllocHGlobal()
states:
This method exposes the Win32 LocalAlloc function from Kernel32.dll.
When AllocHGlobal calls LocalAlloc, it passes a LMEM_FIXED flag, which causes the allocated memory to be locked in place. Also, the allocated memory is not zero-filled.
And the documentation for LocalAlloc()
states:
To free the memory, use the LocalFree function. It is not safe to free memory allocated with LocalAlloc using GlobalFree.
Which is what Marshal.FreeHGlobal()
uses:
FreeHGlobal exposes the LocalFree function from Kernel32.DLL, which frees all bytes so that you can no longer use the memory pointed to by hglobal.
So, it is allowed for C# code to allocate memory using Marshal.AllocHGlobal()
and then for C++ code to free that memory using LocalFree()
. And conversely, for C++ code to allocate memory using LocalAlloc(LMEM_FIXED)
and then for C# code to free that memory using Marshal.FreeHGlobal()
.
Likewise, the Marshal
class also has a Marshal.AllocCoTaskMem()
method:
This method exposes the COM CoTaskMemAlloc function, which is referred to as the COM task memory allocator.
Memory allocated by CoTaskMemAlloc()
is freed with CoTaskMemFree()
:
Frees a block of task memory previously allocated through a call to the CoTaskMemAlloc or CoTaskMemRealloc function.
Which is what Marshal.FreeCoTaskMem()
uses :
FreeCoTaskMem exposes the COM CoTaskMemFree function, which frees all bytes so that you can no longer use the memory that the ptr parameter points to.
So, it is allowed for C# code to allocate memory using Marshal.AllocCoTaskMem()
and then for C++ code to free that memory using CoTaskMemFree()
. And conversely, for C++ code to allocate memory using CoTaskMemAlloc()
and then for C# code to free that memory using Marshal.FreeCoTaskMem()
.
Now, that being said, the memory manager that C++ uses for its new
and delete
operators is implementation-defined. There is no guarantee (or likelihood) that new
uses LocalAlloc()
or CoTaskMemAlloc()
, or that delete
uses LocalFree()
or CoTaskMemFree()
.
So, it is not legal for C# to free any memory allocated with new
, or for C++ to delete
any memory allocated by C#.
Upvotes: 5