C# 是否应将Marshal.FreeHGlobal放在finally块中以确保释放资源?

C# 是否应将Marshal.FreeHGlobal放在finally块中以确保释放资源?,c#,marshalling,finally,unmanagedresources,C#,Marshalling,Finally,Unmanagedresources,我有以下代码块: IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length); Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length); SomeCommandThatCanThrowAnException(); Marshal.FreeHGlobal(unmanagedPointer); 应该将块包装在try中,并将FreeHGlobal命令放置在finally块中。(以

我有以下代码块:

IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
SomeCommandThatCanThrowAnException();
Marshal.FreeHGlobal(unmanagedPointer);
应该将块包装在try中,并将FreeHGlobal命令放置在finally块中。(以防中间命令引发异常)


在这种情况下,finally可以防止内存泄漏似乎是有道理的,但是从我在网上找到的示例来看,finally没有被使用。也许这些资源无论如何都会被自动处置(即使它们是非托管的)

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

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

IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
try
{
    Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
    SomeCommandThatCanThrowAnException();
}
finally
{
    Marshal.FreeHGlobal(unmanagedPointer);
}
为了简洁起见,您发现的示例可能省略了错误处理


如果为长期目的分配非托管内存(即,不在同一方法中释放内存),则可能有兴趣将指针包装到派生自的对象中(例如)

实现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

SafeBuffer用于从C#安全地操作非托管内存,因此根据您的操作(分配非托管内存用于p/Invoke,或从C#操作非托管内存),您应该适当地选择SafeHandle或SafeBuffer作为基类。

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