2011-07-16 31 views
9

Tôi có hàm C++ nhận dữ liệu và tôi gọi nó từ C#. Hàm này nhận một con trỏ tới SAFEARRAY và poplate nó bằng các chuỗi (sử dụng SysAllocString)Phát hành SAFEARRAY từ C++ DLL và C#

Mọi thứ đều ổn, nhưng chương trình đang rò rỉ bộ nhớ.

tôi đã tìm kiếm chút và thấy rằng nếu tôi thêm thuộc tính này để các phương pháp chữ ký:

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

tôi cần phải giải phóng nó trong C++ mã (nơi nó được phân bổ), vì vậy tôi tạo ra chức năng này

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

Và trong dll của tôi đã viết mã này

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

Nhưng tôi đã nhận một ngoại lệ:

Một ngoại lệ unhandled của loại 'System.AccessViolationException' xảy ra ở Tester.exe

thông tin bổ sung: cố gắng để đọc hay ghi bộ nhớ được bảo vệ. Đây thường là dấu hiệu cho thấy rằng bộ nhớ khác bị hỏng.

Điều gì là sai?

+1

bạn cần sử dụng SafeArrayGetUBound thay vì SafeArrayGetDim xem http://msdn.microsoft.com/en-us/library/aed339d5-d962-4adc-ac01-6c15a54c51ca%28VS.85%29 – Yahia

Trả lời

5

Tôi nghĩ bạn nên thử:

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

Lý do cho điều này là bạn đang tuyên bố strServerList như out, vì vậy marshaler Net sẽ cố gắng để chuyển đổi một con trỏ đến một không hợp lệ bộ nhớ (giải phóng) vào một mảng chuỗi, có thể gây ra ngoại lệ.