浮点-C#:从IntPtr转换为float时发生Marshal.Copy()访问冲突



我试图通过ReadProcessMemory()读取内存,然后将读取的值存储在一个浮点中(它肯定是内存中的一个浮点,我已经用另一个实用程序验证了它)以供以后参考,但我尝试的所有操作(BitConverter、Marshal.Copy()等)似乎都失败了。

我看了很多例子,但我不确定我没有理解什么。

我制作了一个简短的程序来测试这个概念。我知道其他技术可以完成这项任务,但我也遇到了麻烦,所以我现在只专注于此。基本上,我将浮点值中的(已知)字节存储在一个4字节的数组中,通过IntPtr指向它,然后使用Marshal.Copy()尝试从IntPtr转换为浮点:

const int FLOAT_SIZE = 4;
byte[] baSource = new byte[FLOAT_SIZE];
IntPtr ipIntermediate = Marshal.AllocHGlobal(sizeof(float));
float[] faDest = new float[1];
baSource[0] = 0xA7;
baSource[1] = 0x68;
baSource[2] = 0xB9;
baSource[3] = 0x44;
ipIntermediate = ((IntPtr)(baSource[0]));
Marshal.Copy(ipIntermediate, faDest, 0, 1); // causes AccessViolation exception

我运行的是Windows 7 64位。我目前的目标是x86版本,但也尝试过"任何CPU",结果都是一样的。持久性似乎也不是问题所在。

如有任何帮助,我们将不胜感激。

((IntPtr)(baSource[0]))的意思是:取数组的第一个元素,并将其转换为IntPtr。实际需要的是:获取字节数组的第一个元素的地址。您可以使用不安全代码或GCHandle来实现这一点:

const int FLOAT_SIZE = 4;
byte[] baSource = new byte[FLOAT_SIZE];
float[] faDest = new float[1];
baSource[0] = 0xA7;
baSource[1] = 0x68;
baSource[2] = 0xB9;
baSource[3] = 0x44;
var gch = GCHandle.Alloc(baSource, GCHandleType.Pinned);
try
{
    var source = gch.AddrOfPinnedObject();
    Marshal.Copy(source, faDest, 0, 1);
}
finally
{
    gch.Free();
}

可能是因为IntPtr是一个指针,所以在对Marshal.Copy.的调用中,它被解释为指针,而不是数据

请注意,有一种更简单的方法可以从其组成字节构建浮点:

float f2 = BitConverter.ToSingle(byteArray, 0);

最新更新