9

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?

vgru
  • 49,838
  • 16
  • 120
  • 201
SharonL
  • 101
  • 1
  • 3
  • 1
    you need to use SafeArrayGetUBound instead of SafeArrayGetDim see http://msdn.microsoft.com/en-us/library/aed339d5-d962-4adc-ac01-6c15a54c51ca%28VS.85%29 – Yahia Jul 26 '11 at 20:49

1 Answers1

5

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.

yms
  • 10,361
  • 3
  • 38
  • 68