在C#中管理返回的字符串指针

时间:2015-04-03 08:58:46

标签: c# c++ .net c

所以我创建了一个用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);

我偶尔会因内存异常而无法处理,但我无法查明原因,因为我不经常这样做。现在我只想知道我是否正确处理返回的字符串?

1 个答案:

答案 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()

手动重建C#字符串

2)有一个返回所需长度的函数,然后传递该长度的StringBuildernew 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)。