将 Intptr 转换为大小

问题描述 投票:0回答:1

我有一个代表内存地址的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);
    }
}
c# interop
1个回答
0
投票

这里的实际问题很简单:传递了错误的

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);

	
© www.soinside.com 2019 - 2024. All rights reserved.