我有一个代表内存地址的IntPtr。有没有一种简单的方法来确定 C# 中 IntPtr 指向的内存地址处的字节大小?
我尝试创建一个循环,但它会导致访问冲突,但不会产生结果。
编辑: 返回 void 并写入流,而不是返回 int。将数据写入文件,但即使使用 try/catch 仍然存在访问冲突。 我可以在知道大小的情况下执行此操作,但在未知的 Scan0 上我可以获得结果,但无法避免访问冲突。如果可以捕获访问冲突,我可以预先确定大小。
public record struct MemoryPointer(IntPtr Scan0, int Size)
{
public async Task Save(string filePath)
{
byte[] bytes = new byte[Size];
using Stream stream = File.Create(filePath);
unsafe
{
byte* pointer = (byte*)Scan0;
for (int index = 0; index < Size; index++, pointer++)
{
bytes[index] = *pointer;
}
}
await stream.WriteAsync(bytes);
}
}
这里的实际问题很简单:传递了错误的
Size
- 我们无能为力,它是此代码的上游。
正如评论中所讨论的,指针本身只是起始位置。在 .NET 中有一个概念定义了这一点——“跨度”。跨度实际上是一个托管指针和要考虑的元素数量(在您的情况下为字节)。如果您将代码切换为根据跨度而不是开始/大小对来思考,那么通常更容易跟踪正在发生的事情。 我提到这一点的主要原因是因为您当前正在将数据复制到
byte[]
以便使用
WriteAsync
。有一种 second
WriteAsync
方法需要 ReadOnlyMemory<byte>
参数。如果您使用同步 Write
API,那么从指针创建一个范围和大小是微不足道的,但对于异步,我们需要一个额外的步骤,我们需要知道 [ReadOnly]Memory<T>
只是对 [ReadOnly]Span<T>
的访问,然后然后我们可以使用这样的东西在我们的跨度和大小上创建一个“记忆”。 长话短说(太晚了!):
var mgr = new UnmanagedMemoryManager<byte>(Scan0, Size);
await stream.WriteAsync(mrg.Memory);