Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Release SAFEARRAY from c++ DLL and c#

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?

like image 320
SharonL Avatar asked Jul 16 '11 18:07

SharonL


People also ask

How do you pass a safe array to a DLL?

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.

How to release data from a safe array in C++?

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

How do I delete a safe array in C++?

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.

What is a safe array?

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):


1 Answers

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.

like image 86
yms Avatar answered Oct 18 '22 06:10

yms