Выпустите SAFEARRAY из c ++ DLL и c # - PullRequest
9 голосов
/ 16 июля 2011

У меня есть функция 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 Ответ

5 голосов
/ 27 июля 2011

Я думаю, вы должны попробовать:

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

Причина этого в том, что вы объявляете strServerList как out, поэтому маршалер .Net попытается преобразовать указатель на недопустимую (освобожденную) память в массив строк, что может вызвать исключение.

...