未对齐4字节时,Monotouch浮点指针将引发NullReferenceException [英] Monotouch floating point pointer throws NullReferenceException when not 4-byte aligned

查看:44
本文介绍了未对齐4字节时,Monotouch浮点指针将引发NullReferenceException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正面临一个我无法理解的问题.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆