Allocate memory in a C++ dll, free in C#

0

I am new in C# and trying to communicate C# with C++ dll. My main purpose is allocating memory in C# using Marshal.AllocHGlobal(), assign values in it and pass the reference of IntPtr to C++ dll. On the side of C++ dll, I'm changing the allocated memory size with malloc(), assign variables. In the end, I print values in C#. Until this point, everything works fine.

But when I try to free allocated memory in C# with Marshal.FreeHGlobal(), I get an error.

Actually, I search a lot to how I should implement my code with these functions. I found a solution that says I must write a function in the DLL for deallocating the memory and call this function. But my manager told me, I need to do this work in C# side. So I can't use that solution. Also, I found some other ideas which use COM but the manager doesn't want to use COM. So I can't use COM. Here some codes;

Allocating the memory in C#

var offset = 0;
var size = Marshal.SizeOf(typeof(dVehicle)) * denemeVehicle.Count();
IntPtr vehPnt;
vehPnt = Marshal.AllocHGlobal(size);

for(var i = 0; i < denemeVehicle.Count(); i++)
{
    Marshal.StructureToPtr(denemeVehicle[i], new IntPtr(vehPnt.ToInt64() + offset), false);
    offset += Marshal.SizeOf(typeof(dVehicle));
}

Changing the allocated memory size in C++

*vehicles = (dVehicle*) malloc(sizeof(dVehicle) * (new_VehSize));

Free the allocated memory

Marshal.FreeHGlobal(vehPnt); // The error shows up in here

And this is error message;

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

c#
c++
memory-management
asked on Stack Overflow May 17, 2019 by Mad_Beggar • edited May 17, 2019 by barbsan

1 Answer

3

Marshal.FreeHGlobal() cannot free memory that was allocated with the C malloc() function. The memory must be "from the global heap allocated by [Marshal.]AllocHGlobal, [Marshal.]ReAllocHGlobal, or any equivalent unmanaged API method."

Internally, Marshal.AllocHGlobal() and Marshal.FreeHGlobal() use the Win32 LocalAlloc() and LocalFree() functions. This is documented on MSDN.

Otherwise, if you want the DLL to allocate the memory however it wants, you will have to make the C# code pass the allocated pointer back to the DLL so it can be freed correctly, ie using the C free() function if the memory is allocated with malloc().

If two modules share memory with each other, but do not agree on a common memory manager (such as one provided by the OS), then the module that allocates the memory must be the same module to free it, as it is the only module that knows how the memory was allocated and thus how to free it.

answered on Stack Overflow May 17, 2019 by Remy Lebeau • edited May 17, 2019 by Remy Lebeau

User contributions licensed under CC BY-SA 3.0