C# 使用AcquirePointer时,处理安全内存AppedViewHandle的正确方法是什么?

C# 使用AcquirePointer时,处理安全内存AppedViewHandle的正确方法是什么?,c#,dispose,memory-mapped-files,unsafe,C#,Dispose,Memory Mapped Files,Unsafe,我有一些代码可以打开一个内存映射文件,并为许多解析操作公开一个ReadOnlySlice。简化课程代码如下: public MemoryMappedViewAccessor Accessor { get; } public SafeMemoryMappedViewHandle Handle { get; } public byte* Memory; private long _size; public Parser(MemoryMappedFile mappedFile, long offse

我有一些代码可以打开一个内存映射文件,并为许多解析操作公开一个
ReadOnlySlice
。简化课程代码如下:

public MemoryMappedViewAccessor Accessor { get; }
public SafeMemoryMappedViewHandle Handle { get; }
public byte* Memory;
private long _size;

public Parser(MemoryMappedFile mappedFile, long offset, long size)
{
    _size = size;
    Accessor = mappedFile.CreateViewAccessor(offset, _size, MemoryMappedFileAccess.Read);
    Handle = Accessor.SafeMemoryMappedViewHandle;
    unsafe
    {
        Handle.AcquirePointer(ref Memory);
    }
}

public ReadOnlySlice<T> GetSpan<T>(int offset, int size)
{
    return new ReadOnlySpan<T>(chunk.Memory, _size).Slice(offset, size);
}

/* other functions exposing various Slice<T> over this */
选项2-将指针释放视为非托管

private bool _isDisposed = false;

protected virtual void Dispose(bool disposing)
{
    if (!_isDisposed)
    {
        if (disposing)
        {
            Accessor.Dispose();
            Handle.ReleasePointer(); // is this even needed?
            Handle.Dispose();
        }

        _isDisposed = true;
    }
}

public void Dispose()
{
    Dispose(true);
}
private bool _isDisposed = false;

protected virtual void Dispose(bool disposing)
{
    if (!_isDisposed)
    {
        if (disposing)
        {
            Accessor.Dispose();
        }

        Handle.ReleasePointer();
        Handle.Dispose();

        _isDisposed = true;
    }
}

~FileChunk()
{
    Dispose(false);
}

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}
在这两种情况下,如果
\u isDisposed
为true,我会在解析逻辑中添加一个检查,以抛出一个
ObjectDisposedException
,以避免UAF错误和内存损坏


当从
安全内存appedviewhandle
中暴露不安全指针时,以下哪种是正确的处置模式?此外,是否值得在处理过程中将
内存
字段设置为null?

您无法确保这一点,因此尝试没有实际意义。您正在通过ReadOnlySpan分发原始指针,您不知道客户机代码何时停止使用它。保持内存字段的私有性并在GetSpan()中执行dispose检查是明智的。@HansPassant谢谢,既然您提到了这一点,这是有道理的。我将记录UAF的可能性,并包括一个警告,不允许
Slice
生存期超过产生它的类实例的生存期。你对选项1和选项2有普遍的偏好吗?我对一次性图案没有任何偏好。sealed关键字总是更好。请记住,没有人知道“UAF”是什么意思。@HansPassant Fair。此应用程序的预期用户群是信息安全专业人员,他们知道UAF的含义:)