Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allocation and deallocation of memory in unmanaged code using platform Invoke (C#)

I want to allocate and deallocate memory in unmanaged code (C++) and we call them functions from managed code (C#). Iam not sure whether the following code is fine without memory leaks or not?

C# code:

[DllImport("SampleDLL.dll")]
public extern void getString([MarshalAs(UnmanagedType.LPStr)] out String strbuilder);

[DllImport("SampleDLL.dll")]
public extern void freeMemory([MarshalAs(UnmanagedType.LPStr)] out String strBuilder);

....

//call to unmanaged code
getString(out str);
Console.WriteLine(str);
freeMemory(out str);

C++ code:

extern void _cdecl getString(char **str)
{
    *str = new char[20];
    std::string temp = "Hello world";
    strncpy(*str,temp.c_str(),temp.length()+1);
}

extern void _cdecl freeMemory(char **str)
{
    if(*str)
        delete []*str;
    *str=NULL;
}
like image 499
user186246 Avatar asked Sep 03 '11 15:09

user186246


1 Answers

No, this cannot work. The pinvoke marshaller is going to try to release the memory for the string with CoTaskMemFree(). It doesn't otherwise know that you have a release function. That's not going to work well, you didn't allocate the string with CoTaskMemAlloc. This is going to be a silent memory leak in XP, a crash in Vista and up.

You have to stop the marshaller from trying to do the right job:

[DllImport("SampleDLL.dll")]
public extern void getString(out IntPtr strptr);

[DllImport("SampleDLL.dll")]
public extern void freeMemory(IntPtr strptr);

Which then requires Marshal.PtrToStringAnsi() in your C# code to marshal the string yourself from the returned pointer.

like image 118
Hans Passant Avatar answered Oct 14 '22 08:10

Hans Passant