I'm calling the following VC++ method
__declspec(dllexport) unsigned char* Get_Version_String()
from C# as follows:
internal static class NativeMethods
{
[DllImport("my.dll"),
CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true,
CallingConvention = CallingConvention.Cdecl)]
internal static extern string Get_Version_String();
}
The above code is in a library which targets .NET 3.5. When I call this from a 3.5 assembly, it works fine; when calling it from a 4.5 assembly, however, it results in
0xC0000374: A heap has been corrupted
After reading this question, I changed my method calls as follows:
[DllImport("my.dll",
EntryPoint = "Get_Version_String",
CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true,
CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr Get_Version_String_PInvoke();
internal static string Get_Version_String()
{
IntPtr ptr = Get_Version_String_PInvoke();
string versionString = Marshal.PtrToStringAnsi(ptr);
return versionString;
}
This works as expected, but the answer from Hans Passant comes with a warning:
The workaround you found is the correct one, the marshaller isn't going to try to release the memory for an
IntPtr
. Do note that this will only actually come to a good end if the C code returns aconst char*
that doesn't need to be released. You have a permanent memory leak if that's not the case.
Since the C++ method does not return const
, I'm going on the assumption that the workaround for my specific function will result in a memory leak.
I cannot change the original method so I found this other question which discusses how to free memory from manged code. However, calling either Marshal.FreeHGlobal(ptr)
or Marshal.FreeCoTaskMem(ptr)
also throw 0xC0000374: A heap has been corrupted.
Can anyone
a) confirm that such a method will indeed suffer from a memory leak, and
b) if so, suggest how to free the memory from the pointer in managed code?
The C++ method body is, simplified, as follows:
unsigned char versionString[50];
__declspec(dllexport) unsigned char* Get_Version_String()
{
strcpy((char *) versionString, "Key1:[xx],Key2:[xx],Key3:[xx],Key4:[xx]");
// string manipulation
return versionString;
}
Thanks in advance, and sorry if this is trivial; I'm neither a C++ nor an Interop expert.