2

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?

3
  • See stackoverflow.com/q/5298268/613130 . What you are doing is wrong and will cause memory leaks Commented Apr 3, 2015 at 9:21
  • What I'm doing is not totally analogous to him, I am using malloc for allocation and, unlike him, am able to use the returned string. I am just worried there is a leak occurring. Regardless I will give it a thorough read but if you could be more specific, that would be greatly appreciated. Commented Apr 3, 2015 at 9:26
  • See even stackoverflow.com/questions/7322503/… Commented Apr 3, 2015 at 9:30

1 Answer 1

2

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).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.