2011-07-16 24 views
9

Mam funkcję C++, która pobiera dane i nazwałem ją z C#. Funkcja uzyskuje wskaźnik do SAFEARRAY i przesyła ją naprzemiennie za pomocą łańcuchów (przy użyciu SysAllocString).Release SAFEARRAY z C++ DLL i C#

Wszystko jest w porządku, ale program jest nieszczelny.

Zrobiłem trochę szukanie i okazało się, że jeśli dodać ten atrybut do podpisu metoda:

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

muszę zwolnić go w C++ kod (gdzie została przydzielona), więc stworzyłem tę funkcję

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

I w moim DLL napisałem ten kod

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

ale mam wyjątek:

nieobsługiwany wyjątek typu „System.AccessViolationException” wystąpił w Tester.exe

Dodatkowe informacje: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często jest to wskazówką, że inna pamięć jest uszkodzona.

Co jest nie tak?

+1

należy użyć SafeArrayGetUBound zamiast SafeArrayGetDim zobacz http://msdn.microsoft.com/en-us/library/aed339d5-d962-4adc-ac01-6c15a54c51ca%28VS.85%29 – Yahia

Odpowiedz

5

myślę, że należy spróbować:

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

Powodem tego jest to, że są deklarowania strServerList jako out, więc marshaler Net będzie starał się przekształcić wskaźnik nieprawidłowego (zwolnionej) pamięci w produkt tablica łańcuchów, która może wywołać wyjątek.

Powiązane problemy