Reputation: 1255
So I created a custom dll callsed FileGuidUtils.dll written in C/C++ and one of the functions returns a WCHAR * string (as a LPWStr in C#). This string gets allocated heap memory inside the function of type (WCHAR *).
Right now I just use the returned string and that's it. Should I be freeing it somewhere in the C#? What code should I use if so? Or is the CLR garbage collector taking care of it for me?
[DllImport(@"FileGuidUtils.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.LPWStr)]
private static extern string getReparseTarget([MarshalAsAttribute(UnmanagedType.LPWStr)] string linkPath);
I occasionally get unhandled out of memory exceptions but am unable to pinpoint the cause because I don't get it very often. For right now I just wanna know if I'm handling the returned string properly?
Upvotes: 2
Views: 454
Reputation: 111940
You are creating a memory leak. .NET can't free memory allocated by malloc
, C++ new
, or any other allocator of Windows, because it can't know which allocator was used (there are some exceptions on this).
Possible solutions:
1) Return a IntPtr
:
private static extern IntPtr getReparseTarget([MarshalAsAttribute(UnmanagedType.LPWStr)] string linkPath);
and have a corresponding
private static extern void freeMemory(IntPtr ptr);
and then manually rebuild the C# string with PtrToStringUni()
2) Have a function that returns the length needed and then pass a StringBuilder
of that length (new StringBuilder(len)
):
private static extern int getReparseTargetLength([MarshalAsAttribute(UnmanagedType.LPWStr)] string linkPath);
private static extern void getReparseTarget([MarshalAsAttribute(UnmanagedType.LPWStr)] string linkPath, [MarshalAsAttribute(UnmanagedType.LPWStr)] StringBuilder output, int maxLen);
3) Use MarshalAs(UnmanagedType.BSTR)
[return: MarshalAs(UnmanagedType.BSTR)]
private static extern string getReparseTarget([MarshalAsAttribute(UnmanagedType.LPWStr)] string linkPath);
The CLR automatically frees strings allocated as BSTR. Note that you will need to create them as BSTR C++-side (with SysAllocString
/SysAllocStringLen
).
Upvotes: 2