我有以下代码块:
IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
SomeCommandThatCanThrowAnException();
Marshal.FreeHGlobal(unmanagedPointer);
是否应该将 block 包裹在 try 中,并将 FreeHGlobal 命令放在 finally block 中。 (以防中间命令抛出异常)。
在这种情况下,finally 似乎可以防止内存泄漏,但是从我在网上找到的示例来看,finally 并没有被使用。也许资源无论如何都会自动处理(即使它们不受管理)。
最佳答案
使用 Marshal.AllocHGlobal 分配的非托管内存不会自动释放。
所以将 Marshal.FreeHGlobal 放在 finally
block 中确实是个好主意:
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 配合得很好,并且完全不需要传递 IntPtr。
SafeBuffers 用于从 C# 安全地操作非托管内存,因此根据您正在执行的操作(分配非托管内存以用于 P/Invoke,或从 C# 操作非托管内存),您应该适本地选择 SafeHandle 或 SafeBuffer 作为基类。
关于c# - 是否应将 Marshal.FreeHGlobal 放在 finally block 中以确保资源得到处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3525932/