未对齐4字节时,Monotouch浮点指针将引发NullReferenceException [英] Monotouch floating point pointer throws NullReferenceException when not 4-byte aligned
问题描述
我正面临一个我无法理解的问题.
I'm facing a problem I just can't understand.
使用Monotouch在C#中使用不安全的指针时,我在设备(ARM)上收到了NullReferenceException,但我无法解释为什么,让我们看一些代码
While playing with unsafe pointers in C# with Monotouch, I get a NullReferenceException on device (ARM), but I can't explain why, let's see some code
var rand = new Random();
var buffer = new byte[2 * 1024 * 1024];
rand.NextBytes(buffer);
fixed (byte* ptr = buffer) {
var ptr2 = ptr + 982515;
//This works
var bfr = new byte[8];
for (int i = 0; i < 8; i++)
bfr[i] = ptr2[i];
var v = BitConverter.ToDouble(bfr, 0);
//This throws a NullReferenceException on device
var v2 = *(double*)ptr2;
Console.WriteLine("v: {0}; v2: {1}", v, v2);
}
它仅在设备上崩溃.与ARM结构化对齐有什么关系?
It only crashes on device. Anything to do with ARM structured alignment ?
修改
经过一番研究,我得出了这样的结论:
After some research I ended with this:
浮点值只能从ARM上4字节对齐的地址中读取
A floating point value can be read only from a 4-bytes aligned address on ARM
static void Main(string[] args) {
Test(982512); //Works
Test(982516); //Works
Test(982515); //Crash on device only
}
unsafe static void Test(int offset) {
var rand = new Random();
var buffer = new byte[2 * 1024 * 1024];
rand.NextBytes(buffer);
fixed (byte* ptr = buffer) {
var ptr2 = ptr + offset;
//Always works
var bfr = new byte[8];
for (int i = 0; i < 8; i++)
bfr[i] = ptr2[i];
var v = BitConverter.ToDouble(bfr, 0);
//Throws a NullReferenceException on device if offset is not 4-byte aligned
var v2 = *(double*)ptr2;
Console.WriteLine("v: {0}; v2: {1}", v, v2);
}
}
关于如何绕过此方法的任何想法吗?
Any idea on how to bypass this ?
推荐答案
在ARM设备上,仅在4字节对齐地址处才可以取消引用浮点值(单,双精度).
On ARM devices, dereferencing a floating-point value (Single, Double) is only possible at a 4-bytes aligned address.
http://www.aleph1.co.uk/第10章手臂结构对齐常见问题解答
所以解决方案是这样的:
So the solution is something like this:
static double ReadDouble(byte* ptr, int offset) {
var ptr2 = ptr + offset;
if ((int)ptr2 % 4 == 0)
return *(double*)ptr2;
else {
var bfr = new byte[8];
for (int i = 0; i < 8; i++)
bfr[i] = ptr2[i];
var v = BitConverter.ToDouble(bfr, 0);
}
}
这篇关于未对齐4字节时,Monotouch浮点指针将引发NullReferenceException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!