I have a c++ function that gets data and I called it from c#. The function gets a pointer to SAFEARRAY and poplate it with strings (using SysAllocString)
Everything is ok, but the program is leaking memory.
I did a little search and found that if I add this attribute to the method signature:
[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
out string[] strServerList
I need to release it in c++ code (where it was allocated), so I created this function
[DllImport("Native.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "DeallocateExternal")]
internal static extern void DeallocateExternal(
[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
out string[] strServerList);
And in my dll i wrote this code
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);
}
But i got an exception:
An unhandled exception of type 'System.AccessViolationException' occurred in Tester.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
What is wrong?
This safe array can be passed as an output parameter in a COM interface method or C-interface DLL function. A safe array is typically referenced via a pointer to its descriptor, which translates to SAFEARRAY* in C++ code.
Again, when you’re done with the safe array’s data, you must call SafeArrayUnaccessData to release access to the safe array. Note that the safe array is still live in memory, until SafeArrayDestroy is called on it. This is a companion article to Simplify Safe Array Programming in C++ with CComSafeArray
If you write code that owns the SAFEARRAY, once you’re done with it, you must call the SafeArrayDestroy function to release the memory allocated by the safe array. That function accepts a single parameter, that is, a pointer to a SAFEARRAY descriptor associated to the safe array to be deleted.
Introducing the SAFEARRAY Data Structure A safe array is represented using a C data structure named SAFEARRAY, which is defined in the <OAIdl.h> Windows Platform SDK header. The SAFEARRAY structure is described in detail in the Windows Dev Center (bit.ly/2fLXY6K):
I think you should try:
...
SafeArrayDestroy(*psa);
*psa = NULL
...
The reason for this is that you are declaring strServerList
as out
, so the .Net marshaler will try to convert a pointer to an invalid (freed) memory into an array of string, which may provoke the exception.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With