【问题标题】:dynamic way to free intPtr释放 intPtr 的动态方法
【发布时间】:2026-01-06 18:55:01
【问题描述】:

我有一个大类,在很多地方我需要将数组转换为 intPtr

IntPtr convertToIntPtr(Array input)
{
    if (input != null)
    {
        int s = Marshal.SizeOf(input.GetValue(0).GetType()) * input.Length;
        System.IntPtr p = Marshal.AllocHGlobal(s);

        return p;
    }
    return new IntPtr();
}

我知道可以使用Marshal.FreeHGlobal(IntPtr) 释放每个指针。

我的问题是: - 将garbagecollector免费intptr一旦使用 - 如果没有,我怎样才能在关闭或处置类时释放所有这些,任何要使用的事件,以便当 intpntr 没有远被删除时

【问题讨论】:

  • 为什么需要非托管内存?也许你没有
  • 包装它,从SafeBuffer 派生一个类。喜欢this
  • @DavidHeffernan 不幸的是我使用需要 intptr 的 3D Dlls
  • 不一定。只有当他们引用您的数据时。也许你只需要传递double[]

标签: c# intptr


【解决方案1】:

不,你分配的内存是非 GC 处理的内存,所以它不会被释放(技术上它会在你的程序结束时被释放......但我认为这不是你想要的)。

您可以做的是将IntPtr 封装在一次性对象中。

public sealed class ArrayToIntPtr : IDisposable
{
    public IntPtr Ptr { get; protected set; }

    public ArrayToIntPtr(Array input)
    {
        if (input != null)
        {
            int s = Marshal.SizeOf(input.GetValue(0).GetType()) * input.Length;
            Ptr = Marshal.AllocHGlobal(s);
        }
        else
        {
            Ptr = IntPtr.Zero;
        }
    }

    ~ArrayToIntPtr()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
    }

    protected void Dispose(bool disposing)
    {
        if (Ptr != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(Ptr);
            Ptr = IntPtr.Zero;
        }

        if (disposing)
        {
            GC.SuppressFinalize(this);
        }
    }
}

(注意类是sealed,所以Dispose(bool disposing)不是virtual

【讨论】:

    【解决方案2】:

    不,垃圾收集器不会自动释放 IntPtr。由您自己管理。我建议尽可能避免这样做,但是当你需要这样做时,你应该实现dispose pattern

    【讨论】: