Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 非4字节对齐时,单触浮点指针引发NullReferenceException_C#_Ios_.net_Xamarin.ios_Unsafe - Fatal编程技术网

C# 非4字节对齐时,单触浮点指针引发NullReferenceException

C# 非4字节对齐时,单触浮点指针引发NullReferenceException,c#,ios,.net,xamarin.ios,unsafe,C#,Ios,.net,Xamarin.ios,Unsafe,我正面临一个我无法理解的问题 在使用Monotouch在C#中使用不安全指针时,我在设备(ARM)上得到了一个NullReferenceException,但我无法解释原因,让我们来看一些代码 var rand = new Random(); var buffer = new byte[2 * 1024 * 1024]; rand.NextBytes(buffer); fixed (byte* ptr = buffer) { var ptr2 = ptr + 982515;

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

在使用Monotouch在C#中使用不安全指针时,我在设备(ARM)上得到了一个NullReferenceException,但我无法解释原因,让我们来看一些代码

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);
}
var rand=new Random();
var buffer=新字节[2*1024*1024];
下一字节随机数(缓冲区);
固定(字节*ptr=缓冲区){
var ptr2=ptr+982515;
//这很有效
var bfr=新字节[8];
对于(int i=0;i<8;i++)
bfr[i]=ptr2[i];
var v=位转换器。ToDouble(bfr,0);
//这会在设备上引发NullReferenceException
变量v2=*(双*)ptr2;
WriteLine(“v:{0};v2:{1}”,v,v2);
}
它只在设备上崩溃。 与手臂结构对齐有关吗

编辑

经过一番研究后,我得出以下结论:

浮点值只能从ARM上的4字节对齐地址读取

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);
    }
}
static void Main(字符串[]args){
测试(982512);//工作
测试(982516);//工作
测试(982515);//仅在设备上崩溃
}
不安全静态空隙试验(内部偏移){
var rand=new Random();
var buffer=新字节[2*1024*1024];
下一字节随机数(缓冲区);
固定(字节*ptr=缓冲区){
var ptr2=ptr+偏移量;
//总是有效的
var bfr=新字节[8];
对于(int i=0;i<8;i++)
bfr[i]=ptr2[i];
var v=位转换器。ToDouble(bfr,0);
//如果偏移量不是4字节对齐的,则在设备上引发NullReferenceException
变量v2=*(双*)ptr2;
WriteLine(“v:{0};v2:{1}”,v,v2);
}
}

想知道如何绕过这个问题吗?

在ARM设备上,只有在4字节对齐的地址上才能取消对浮点值(单、双)的引用

所以解决方案是这样的:

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);
    }
}
static double ReadDouble(字节*ptr,int偏移量){
var ptr2=ptr+偏移量;
如果((int)ptr2%4==0)
返回*(双*)ptr2;
否则{
var bfr=新字节[8];
对于(int i=0;i<8;i++)
bfr[i]=ptr2[i];
var v=位转换器。ToDouble(bfr,0);
}
}

您需要发布实际代码-该代码无法编译(
buffer
修复的
块中重新声明)。我在
固定的
块之前定义了
buffer
并删除了另一个
buffer
声明,我尝试了这段代码,它正常工作,没有任何异常。考虑到这一点,也许您有某种多线程问题?我编辑了代码。如前所述,它并不总是崩溃,但只有一些特定的数据,我将尝试发布一个。如果我再次编辑代码,您现在可以重现崩溃。问题是-显然,(double*)ptr2返回null。然后*ptr2导致异常。。