我有一些代码可以打开一个内存映射文件,并公开一个ReadOnlySlice<T>
用于许多解析操作。下面是简化的类代码:
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 */
显然,这需要我的班实现IDisposable
,但我不确定不安全资源和安全资源之间的界限在哪里。一个reference I found表示SafeMemoryMappedViewHandle
是一个托管资源,应该这样处理,但是没有提到ReleasePointer
会如何变化,或者是否ReleasePointer
应该是在Dispose
之前调用。
我的看法是,以下两种Dispose
模式是我的选择:
选项1-将所有内容视为托管内容
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);
}
选项2-将指针释放视为不受管理
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);
}
在这两种情况下,如果ObjectDisposedException
为true,我都将在检查逻辑中添加一个检查以抛出_isDisposed
,以避免UAF错误和内存损坏。
从SafeMemoryMappedViewHandle
中暴露不安全的指针时,其中哪些是正确的处置模式?另外,是否值得在处置期间将Memory
字段设置为null?