2

我正在尝试通过 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”,只是为了获得相同的结果。字节顺序似乎也不是问题。

任何帮助将不胜感激。

4

2 回答 2

2

((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();
}
于 2013-02-05T23:00:26.210 回答
0

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

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

float f2 = BitConverter.ToSingle(byteArray, 0);
于 2013-02-05T22:55:46.997 回答