Marshal.FreeHGlobal应该放在finally块中以确保资源处置?

我有以下代码块:

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

是否应该在try中包装块,并将FreeHGlobal命令放在finally块中。 (如果middle命令抛出exception)。

在这种情况下最终会阻止内存泄漏似乎是有道理的,但是从我在网上找到的例子中,最终没有使用。 也许资源会被自动处理掉(即使它们是不受管理的)。

分配给Marshal.AllocHGlobal的非托管内存不会自动释放。

因此将Marshal.FreeHGlobal放入finally块中确实是一个好主意:

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

您发现的示例可能会因为简洁而省略error handling。


如果您为长期目的分配非托管内存(即不在同一方法中释放它),您可能有兴趣将指针包装在派生自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。

SafeBuffers用于从C#安全地操作非托管内存,因此根据您正在执行的操作(分配非托管内存以用于P / Invoke,或从C#操作非托管内存),您应该选择SafeHandle或SafeBuffer作为基类。

绝对。 它永远不会自动释放,它是非托管内存。