2010-08-19 42 views
5

我有下面的代碼塊:Marshal.FreeHGlobal應該放在finally塊中以確保資源被丟棄嗎?

IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length); 
Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length); 
SomeCommandThatCanThrowAnException(); 
Marshal.FreeHGlobal(unmanagedPointer); 

如果該塊被包裹在一試,和FreeHGlobal命令被放置在最後塊。 (如果中間命令引發異常)。

似乎有意義的是,在這種情況下最終會防止內存泄漏,但是從我在網上找到的例子中,終於沒有被使用。無論如何,資源可能會自動處理(儘管它們是非託管的)。

回答

12

未分配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#中的非託管內存。 。

2

絕對如此。它從來沒有自動釋放,它是非託管內存。

相關問題