2011-02-09 2 views
1

C++ 기반 DLL을 사용하는 C# 기반 UI가 있습니다. 내 요구 사항은 C#에서 DLL로 큰 메모리 덩어리를 전달하는 것이었다. DLL이이 메모리 버퍼에 쓰고 C#으로 다시 전달합니다. 나는 이것을하기 위해 IntPtr & 전역 메모리 함수를 사용했다. 모든 것이 잘 작동합니다.Marshal.FreeHGlobal() 작동 방식은 무엇입니까?

질문은 Marshal.FreeHGlobal()이 메모리를 정리했는지 확인하는 방법입니다. 나는 MB의 관점에서 큰 메모리 덩어리를 사용하고있다. 따라서 메모리를 즉시 지우고 싶습니다.

+0

"청소"를 사용하면 보안에 관심이 있음을 나타내지 만 실제로 메모리가 해제되었는지 여부를 알고 싶다고 생각합니다. 나 맞아? –

+0

예, 현재 메모리를 확보하는 것이 더 중요합니다. – vrrathod

+0

문서에서는 AllocHGlobal() 및 FreeHGlobal()이 Win32 LocalAlloc() 및 LocalFree() 함수를 둘러싼 래퍼 일 뿐이라고합니다. 같은 양의 allocator를 사용하고있는 한 괜찮을 것이다. – Luke

답변

4

Marshal.FreeHGlobal에 유효한 핸들을 전달하면 이 해제됩니다. 그러나이 메서드는 값을 반환하지 않으므로 해당 메서드가 정리되었는지 여부를 알 수 없습니다.

FreeHGlobal에 올바른 것을 전달하는지 의심스러운 점이 있으면 코드가 깨끗해야한다고 생각합니다. 당신이 정말로 있는지 확인하려면 경우에, 당신이 당신이 FreeHGlobal에 전달했을 것이라고 핸들을 전달하는 LocalFree Windows API 함수를 호출 할 수 있습니다

[DllImport("kernel32", SetLastError=true)] 
static extern IntPtr LocalFree(IntPtr mem); 

// Now, to free a block of memory allocated with Marshal.AllocHGlobal 
IntPtr rslt = LocalFree(memPtr); 
if (rslt == IntPtr.Zero) 
{ 
    // success! 
} 
else 
{ 
    int err = Marshal.GetLastWin32Error(); 
    // do something with the error. 
} 
내가 제안

그러나,이 작업을 수행 할 경우 것으로, 나중에 LocalAlloc을 호출하여 Marshal.AllocHGlobal을 호출하는 대신 메모리를 할당하는 것이 좋습니다. 이후 버전의 .NET에서는 LocalAlloc 이외의 다른 방법을 사용하여 관리되지 않는 메모리를 할당 할 수 있습니다. 그럴 경우 LocalFree에 의존하는 코드가 중단됩니다.

+0

이것은 완벽하게 작동했습니다. 감사. – vrrathod

+0

'Marshal.FreeHGlobal'이 계약 상으로'LocalFree'를 호출합니다 https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.freehglobal(v=vs.110).aspx –

0

관리되는 메모리에 배열을 할당 한 다음 GCHandle을 만들어 관리되지 않는 메모리에서 액세스 할 수있게 할 수도 있습니다.

예를 들어 여기서 PowerReadACValue을 호출합니다. Win32 API 함수는 LPBYTE 버퍼 (이는 BYTE*과 같습니다)를 사용합니다.

먼저 "null 포인터"(IntPtr.Zero)를 호출하여 필요한 크기 버퍼를 알려줍니다 (bufferSize로 출력 됨). 그런 다음 버퍼를 할당하고 GCHandleAddrOfPinnedObject을 통해 포인터를 전달합니다.

uint type; 
uint bufferSize = 0; 

if (SafeNativeMethods.PowerReadACValue(IntPtr.Zero, this.m_planHandle, ref subGroupOfPowerSettingsGuid, ref powerSettingGuid, out type, IntPtr.Zero, ref bufferSize) != 0) 
{ 
    throw new Win32Exception(); 
} 

byte[] buffer = new byte[bufferSize]; 
GCHandle bufferPointer = default(GCHandle); 
try 
{ 
    bufferPointer = GCHandle.Alloc(buffer, GCHandleType.Pinned); 
    if (SafeNativeMethods.PowerReadACValue(IntPtr.Zero, this.m_planHandle, ref subGroupOfPowerSettingsGuid, ref powerSettingGuid, out type, bufferPointer.AddrOfPinnedObject(), ref bufferSize) != 0) 
     throw new Win32Exception(); 
} 
finally 
{ 
    if (bufferPointer.IsAllocated) 
     bufferPointer.Free(); 
} 

또한, 나는 또한 나에게 IntPtr를 반환 Marshal.AllocHGlobal로 버퍼를 할당 한 수 한 다음 나중에 무료로 Marshal.FreeGlobal에 있지만이 경우에는 관리 코드에서 배열의 데이터를 사용할 필요가있다. 배열 포인터를 관리되는 코드에서 건드리지 않고 다른 관리되지 않는 함수에 전달하려고한다면 GCHandle이 활성화되어있는 동안 메모리가 가비지 컬렉터에 영향을주는 메모리에 잠겨 있습니다.).

관련 문제