You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

处置NativeMemory<T>时,应将其视为托管还是非托管资源?

关于NativeMemory的资源处置类型判定

首先,.NET官方推荐的Dispose模式核心实现如下:

protected virtual void Dispose(bool disposing)
{
    if (_disposed)
    {
        return;
    }

    if (disposing)
    {
        // TODO: 释放托管状态(托管对象)
    }

    // TODO: 释放非托管资源(非托管对象),并在下方重写终结器
    // TODO: 将大字段设为null

    _disposed = true;
}

相关代码实现

NativeMemory 托管包装类

using System.Runtime.InteropServices;
using Whatever.Extensions;

namespace XYZ.Extensions;

public sealed class NativeMemory<T> : DisposableAsync where T : unmanaged
{
    public unsafe NativeMemory(uint count, uint alignment = 1)
    {
        ArgumentOutOfRangeException.ThrowIfZero(alignment);

        Length = count * (uint)sizeof(T);

        Pointer = (nint)NativeMemory.AlignedAlloc(Length, alignment);

        Manager = new NativeMemoryManager<T>((T*)Pointer, (int)Length);

        Manager.Memory.Span.Clear();
    }

    public NativeMemoryManager<T> Manager { get; }

    public uint Length { get; }

    public nint Pointer { get; }

    protected override ValueTask DisposeAsyncCore()
    {
        DisposeNative();

        return ValueTask.CompletedTask;
    }

    protected override void DisposeNative()
    {
        DisposePointer();
    }

    private unsafe void DisposePointer()
    {
        NativeMemory.AlignedFree(Pointer.ToPointer());
    }
}

NativeMemoryManager 内存管理器

using System.Buffers;

namespace ISO9660.Extensions;

public sealed unsafe class NativeMemoryManager<T>(T* pointer, int length)
    : MemoryManager<T> where T : unmanaged
{
    private T* Pointer { get; } = pointer;

    private int Length { get; } = length;

    protected override void Dispose(bool disposing)
    {
        // NOP
    }

    public override Span<T> GetSpan()
    {
        return new Span<T>(Pointer, Length);
    }

    public override MemoryHandle Pin(int elementIndex = 0)
    {
        ArgumentOutOfRangeException.ThrowIfNegative(elementIndex);

        ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(elementIndex, Length);

        return new MemoryHandle(Pointer + elementIndex);
    }

    public override void Unpin()
    {
        // NOP
    }
}

Disposable 辅助类

using System;

#nullable disable
namespace Whatever.Extensions
{
  public abstract class Disposable : IDisposable
  {
    protected bool IsDisposed { get; set; }

    public void Dispose()
    {
      this.Dispose(true);
      GC.SuppressFinalize((object) this);
    }

    protected virtual void Dispose(bool disposing)
    {
      if (this.IsDisposed)
        return;
      this.DisposeNative();
      if (disposing)
        this.DisposeManaged();
      this.IsDisposed = true;
    }

    protected virtual void DisposeManaged() { }

    protected virtual void DisposeNative() { }

    ~Disposable() => this.Dispose(false);
  }
}

DisposableAsync 辅助类

using System;
using System.Threading.Tasks;

#nullable enable
namespace Whatever.Extensions
{
  public abstract class DisposableAsync : Disposable, IAsyncDisposable
  {
    public async ValueTask DisposeAsync()
    {
      DisposableAsync disposableAsync = this;
      await disposableAsync.DisposeAsyncCore().ConfigureAwait(false);
      GC.SuppressFinalize((object) disposableAsync);
    }

    protected virtual async ValueTask DisposeAsyncCore()
    {
      await new ValueTask().ConfigureAwait(false);
    }
  }
}

问题

处置NativeMemory<T>时,应将其视为托管资源还是非托管资源?

解答

要明确这个问题,得拆分NativeMemory<T>内部的资源类型:

  • 非托管资源部分:通过NativeMemory.AlignedAlloc分配的内存是典型的非托管资源——CLR垃圾回收器无法追踪这类内存,必须手动调用NativeMemory.AlignedFree释放,否则会造成内存泄漏。这部分操作不受disposing参数影响,无论主动调用Dispose还是终结器触发,都必须执行释放。
  • 托管资源部分:NativeMemoryManager<T>是托管对象,但它的Dispose方法是空实现,且仅封装了非托管内存指针,没有持有需要额外释放的托管资源,所以不需要特殊的托管资源释放逻辑。

回到NativeMemory<T>的处置逻辑:它当前的实现是正确的——将非托管内存释放放在DisposeNative中,无论disposing是true还是false都会执行,符合Dispose模式处理非托管资源的要求,且无需在DisposeManaged中添加额外逻辑。

总结:NativeMemory<T>本身是托管包装类,但核心持有非托管资源(对齐分配的内存),处置时重点是处理非托管资源的释放,其托管成员无需额外处置操作。

内容的提问来源于stack exchange,提问作者aybe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 01:12:32