释放C++ DLL和C#中的SAFEARRAY

9

我有一个C++函数,用于获取数据,并从C#中调用它。该函数获取指向SAFEARRAY的指针,并使用SysAllocString将其填充为字符串。

一切正常,但程序存在内存泄漏问题。

我进行了一些搜索,并发现如果在方法签名中添加此属性:

 [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
 out string[] strServerList

我需要在C++代码中释放它(它是在那里分配的),因此我创建了这个函数。
 [DllImport("Native.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "DeallocateExternal")]
 internal static extern void DeallocateExternal(
 [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
 out string[] strServerList);

在我的dll中,我编写了以下代码。
void DeallocateExternal(SAFEARRAY** psa)
{
    LONG cDims = SafeArrayGetDim(*psa);
    BSTR* pvData = (BSTR*)((*psa)->pvData); 
    for (LONG x = 0; x < cDims; x++)
    {
       SysFreeString(pvData[x]);
    }
    SafeArrayDestroy(*psa); 
}

但是我遇到了一个异常:

未经处理的类型为 'System.AccessViolationException' 的异常发生在 Tester.exe 中

额外信息:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

出了什么问题?


1
你需要使用SafeArrayGetUBound而不是SafeArrayGetDim,参见http://msdn.microsoft.com/en-us/library/aed339d5-d962-4adc-ac01-6c15a54c51ca%28VS.85%29。 - Yahia
1个回答

5

我认为你应该尝试:

...
SafeArrayDestroy(*psa); 
*psa = NULL
...

这是因为你将strServerList声明为out,所以.Net编译器会尝试将一个指向无效(已释放)内存的指针转换为字符串数组,这可能引发异常。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接