Liberar SAFEARRAY da DLL c ++ e c #

9

Eu tenho uma função em c ++ que obtém dados e chamo de c #. A função obtém um ponteiro para SAFEARRAY e poplate-lo com seqüências de caracteres (usando SysAllocString)

Tudo está ok, mas o programa está vazando memória.

Eu fiz uma pequena pesquisa e descobri que se eu adicionar esse atributo à assinatura do método:

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

Eu preciso liberá-lo em código c ++ (onde foi alocado), então criei esta função

 [DllImport("Native.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "DeallocateExternal")]
 internal static extern void DeallocateExternal(
 [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
 out string[] strServerList);

E na minha dll eu escrevi este código

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); 
}

Mas recebi uma exceção:

  

Ocorreu uma exceção sem tratamento do tipo 'System.AccessViolationException' no Tester.exe

     

Informações adicionais: tentativa de ler ou gravar memória protegida. Isso geralmente é uma indicação de que outra memória está corrompida.

O que está errado?

    
por SharonL 16.07.2011 в 20:35
fonte

1 resposta

5

Acho que você deveria tentar:

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

A razão para isso é que você está declarando strServerList as out , portanto, o empacotador .net tentará converter um ponteiro para uma memória inválida (liberada) em uma matriz de seqüência de caracteres, que pode provocar a exceção.

    
por yms 26.07.2011 / 22:37
fonte