是否应将Marshal.FreeHGlobal放置在final块中以确保资源被处置? [英] Should Marshal.FreeHGlobal be placed in a finally block to ensure resources are disposed?

查看:120
本文介绍了是否应将Marshal.FreeHGlobal放置在final块中以确保资源被处置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码块:

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

是否应该尝试将块包装起来,然后将FreeHGlobal命令放置在finally块中. (以防中间命令抛出异常).

Should the block be wrapped in a try, and the FreeHGlobal command be placed in a finally block. (In case the middle command throws an exception).

在这种情况下,最终将防止内存泄漏似乎很有意义,但是从我在网上找到的示例来看,最终没有使用.也许资源无论如何都会自动处置(即使它们是不受管理的).

It seems to make sense that finally would prevent memory leaks in this case, however from examples that I have found online, finally is not used. Perhaps the resources get automatically disposed of anyway (even though they are unmanaged).

推荐答案

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

Unmanaged memory allocated with Marshal.AllocHGlobal is not automatically released.

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

So putting Marshal.FreeHGlobal in a finally block is indeed a good idea:

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

为简便起见,您发现的示例可能省略了错误处理.

The examples you've found probably omit error handling for brevity.

如果出于长期目的分配非托管内存(即不在同一方法中释放它),则可能有兴趣将指针包装在从

If you're allocating unmanaged memory for long-term purposes (i.e. not freeing it within the same method), you might be interested in wrapping the pointer in an object that derives from SafeHandle (such as SafeBuffer).

SafeHandle 实现IDisposable模式,因此,当您处置对象或垃圾收集器收集对象时,非托管内存将被释放. SafeHandle也是从CriticalFinalizerObject类派生的,这意味着它将从CLR得到特殊处理,以确保真正释放了内存.

SafeHandle implements the IDisposable pattern, so the unmanaged memory will be freed when you dispose the object or when the garbage collector collects the object. SafeHandle also derives from the CriticalFinalizerObject class which means it will get special treatment from the CLR to make sure the memory is really freed.

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确实是野兽,因此请注意.

Note: SafeBuffer is quite a beast, so caution is advised.

注2:SafeHandles与P/Invoke配合使用效果很好,并且无需完全传递IntPtrs.

Note 2: SafeHandles work well with P/Invoke and eliminate the need to pass around IntPtrs entirely.

SafeBuffers被安全地从C#操纵非托管内存,所以这取决于你在做什么(分配与的P/Invoke使用非托管内存,或从C#操纵非托管内存),你应该适当选择的SafeHandle或SafeBuffer作为基类.

SafeBuffers are for safely manipulating unmanaged memory from C#, so depending on what you're doing (allocating unmanaged memory for use with P/Invoke, or manipulating unmanaged memory from C#) you should choose SafeHandle or SafeBuffer as base class appropriately.

这篇关于是否应将Marshal.FreeHGlobal放置在final块中以确保资源被处置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆