2011-07-16 8 views
9

Tengo una función C++ que obtiene los datos y lo llamé desde C#. La función obtiene un puntero a SAFEARRAY y lo puebla con cadenas (usando SysAllocString)lanzamiento SAFEARRAY de C++ y C# DLL

Todo está bien, pero el programa está perdiendo memoria.

Hice un poco de búsqueda y encontraron que si añado este atributo a la firma del método:

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

necesito para liberarlo en código C++ (en el que se asignó), por lo que creó esta función

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

Y en mi DLL que escribí 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); 
} 

pero me dio una excepción:

Una excepción no controlada del tipo 'System.AccessViolationException' ocurrieron en Tester.exe

Información adicional: Intento de leer o escribir en la memoria protegida. Esto a menudo es una indicación de que otra memoria está corrupta.

¿Qué le pasa?

+1

es necesario utilizar SafeArrayGetUBound en lugar de ver SafeArrayGetDim http://msdn.microsoft.com/en-us/library/aed339d5-d962-4adc-ac01-6c15a54c51ca%28VS.85%29 – Yahia

Respuesta

5

creo que debería probar:

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

La razón de esto es que se está declarando strServerList como out, por lo que el contador de referencias .Net tratará de convertir un puntero a una memoria no válida (liberado) en una matriz de cadena, que puede provocar la excepción.