未分配Marshal.AllocHGlobal的非託管內存不會自動釋放。
所以把Marshal.FreeHGlobal在finally
塊的確是一個不錯的主意:
IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
try
{
Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
SomeCommandThatCanThrowAnException();
}
finally
{
Marshal.FreeHGlobal(unmanagedPointer);
}
你可能已經發現的例子忽略錯誤處理簡潔。
如果你長期目的分配非託管內存(即在同一方法中沒有釋放它),你可能會感興趣的包裹中,從SafeHandle獲得的對象指針(如SafeBuffer) 。
SafeHandle實現了IDisposable模式,因此當您處理對象或垃圾收集器收集對象時,非託管內存將被釋放。 SafeHandle也從CriticalFinalizerObject類派生,這意味着它將得到CLR的特殊待遇,以確保內存真正被釋放。
class HGlobal : SafeBuffer
{
public HGlobal(int cb)
: base(true)
{
this.SetHandle(Marshal.AllocHGlobal(cb));
this.Initialize((ulong)cb);
}
protected override bool ReleaseHandle()
{
Marshal.FreeHGlobal(this.handle);
return true;
}
}
例子:
using (var h = new HGlobal(buffer.Length))
{
h.WriteArray(0, buffer, 0, buffer.Length);
}
注:SafeBuffer是一個相當獸,所以建議謹慎。注意2:SafeHandles可以很好地與P/Invoke配合使用,並且不需要完全傳遞IntPtrs。你可以選擇SafeHandle或SafeBuffer作爲基類,它可以根據你正在做的事情(分配非託管內存用於P/Invoke,或者從C#操作非託管內存),安全地操作C#中的非託管內存。 。
來源
2010-08-19 20:38:55
dtb