所以我创建了一个用C / C ++编写的自定义dll调用FileGuidUtils.dll,其中一个函数返回一个WCHAR *字符串(作为C#中的LPWStr)。该字符串在类型(WCHAR *)的函数内获得分配的堆内存。
现在我只使用返回的字符串,就是这样。我应该在C#的某个地方释放它吗?如果是这样,我应该使用什么代码?或者CLR垃圾收集器是否为我处理它?</ p>
[DllImport(@"FileGuidUtils.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.LPWStr)]
private static extern string getReparseTarget([MarshalAsAttribute(UnmanagedType.LPWStr)] string linkPath);
我偶尔会因内存异常而无法处理,但我无法查明原因,因为我不经常这样做。现在我只想知道我是否正确处理返回的字符串?
答案 0 :(得分:2)
您正在创建内存泄漏。 .NET无法释放由malloc
,C ++ new
或Windows的任何其他分配器分配的内存,因为它无法知道使用了哪个分配器(这有一些例外) )。
可能的解决方案:
1)返回IntPtr
:
private static extern IntPtr getReparseTarget([MarshalAsAttribute(UnmanagedType.LPWStr)] string linkPath);
并有相应的
private static extern void freeMemory(IntPtr ptr);
然后使用PtrToStringUni()
2)有一个返回所需长度的函数,然后传递该长度的StringBuilder
(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)使用MarshalAs(UnmanagedType.BSTR)
[return: MarshalAs(UnmanagedType.BSTR)]
private static extern string getReparseTarget([MarshalAsAttribute(UnmanagedType.LPWStr)] string linkPath);
CLR自动释放分配为BSTR的字符串。请注意,您需要将它们创建为BSTR C ++ - (SysAllocString
/ SysAllocStringLen
)。