使用 Microsoft.Win32.SafeHandles 与 Marshal.AllocHGlobal 和 Marshal.FreeHGlobal

Using Microsoft.Win32.SafeHandles vs Marshal.AllocHGlobal and Marshal.FreeHGlobal

我有一个 .Net class,它使用 Marshal.AllocHGlobalstruct 分配非托管内存,然后使用 Marshal.FreeHGlobal.

处理它

我知道 classes Microsoft.Win32.SafeHandles 提供了处理这个的包装器,但不清楚如何实例化它们(许多没有构造函数)——我应该写一个抽象基础 class 的具体实现,或者有什么方法可以在 extern 声明中使用它们?

子类化 SafeHandle 的主要问题是 Marshal.DestroyStructure 您需要结构的 Type... 这让一切都变得更加复杂。

你不能使用泛型(因为它们与 pinvoke 不兼容)...所以你可以有多个 SafeHandle 子类(每个 Type 一个),或者一个 属性 在 SafeHandle 中使用您手动设置的结构类型...或者您可以使 SafeHandle 的构造函数接受要编组的结构并设置 Type在 属性.

我正在使用最后两个 "options"(属性 Type 可以手动设置或可以由构造函数自动设置)

MySafeHandle的例子:

public class MySafeHandle : SafeHandle
{
    public Type Type { get; set; }

    public MySafeHandle() : base(IntPtr.Zero, true)
    {
    }

    public MySafeHandle(object obj)
        : base(IntPtr.Zero, true)
    {
        if (obj != null)
        {
            Type = obj.GetType();
            int size = Marshal.SizeOf(obj);

            try
            {
            }
            finally
            {
                // the finally part can't be interrupted by
                // Thread.Abort
                handle = Marshal.AllocHGlobal(size);
                Marshal.StructureToPtr(obj, handle, false);
            }
        }
    }

    public override bool IsInvalid
    {
        get { return handle == IntPtr.Zero; }
    }

    [SecurityCritical]
    protected override bool ReleaseHandle()
    {
        if (handle != IntPtr.Zero)
        {
            if (Type == null)
            {
                throw new InvalidOperationException();
            }

            try
            {
            }
            finally
            {
                Marshal.DestroyStructure(handle, Type);
                Marshal.FreeHGlobal(handle);
                handle = IntPtr.Zero;
            }

            return true;
        }

        return false;
    }
}

您应该使用的构造函数是使用 Marshal.StructureToPtr 编组结构的构造函数。它的优点是它保存了结构的类型,以便以后可以使用它到 Marshal.DestroyStructure.