[英]How to use C# stackalloc and keep the same code structure?
我有一个方法MemRead
读取内存并返回一个字节数组
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref byte lpBuffer, int dwSize, out int lpNumberOfBytesRead);
public static Span<byte> MemRead(this Process process, IntPtr address, int size)
{
if (process == null)
throw new ArgumentException("Process is null");
Span<byte> buffer = new byte[size];
bool success = NativeMethods.ReadProcessMemory(process.Handle, address, ref MemoryMarshal.GetReference(buffer), size, out int lpNumberOfBytesRead);
if (!success)
throw new Exception("ReadProcessMemory failed");
if (lpNumberOfBytesRead < size)
throw new Exception($"ReadProcessMemory failed : {lpNumberOfBytesRead} bytes read out of {size}");
return buffer;
}
我有方法MemReadInt32
, MemReadBool
,...调用MemRead
并进行转换
public static int MemReadInt32(this Process process, IntPtr address)
{
return BitConverter.ToInt32(MemRead(process, address, 4));
}
现在我想在堆栈而不是堆上分配缓冲区,所以我更改了这一行
Span<byte> buffer = new byte[size];
到
Span<byte> buffer = stackalloc byte[size];
编译器抛出错误,因为堆栈分配的数组不能在声明范围之外公开。 这是有道理的,这可以防止对堆的潜在提升。
但是后来我被迫将转换代码放置在与读取代码相同的方法中。 读取代码将针对每个MemReadInt32
、 MemReadBool
、 ...
如何避免重复ReadMem
代码,并且仍然获得堆栈分配?
这是一个非常简单的解决方案,所以我可能会遗漏一些东西,但是为什么不将缓冲区作为参数呢? 然后,您可以在调用函数中堆栈分配一个合适大小的 Span。 否则,我认为没有办法在函数返回后无法访问其堆栈空间(除非通过将指针传递出去并希望数组仍然存在 - 尽管经过一些测试,它似乎从未存在 - 也许是 CLR作为安全预防措施覆盖它?)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.