本文介绍了Monotouch 在不可为空的对象上因 NullReferenceException 崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是崩溃日志(简短):

Here is the crash log ( short ):

2013-04-24 19:56:24 +0000 Memotion 未处理的托管异常:未将对象引用设置为对象的实例 (System.NullReferenceException)
在 Pipedream.UI.UIElement.set_Size(Vector2 值)[0x00000] 中:0
在 Pipedream.UI.StageLayer..ctor (Pipedream.ComponentID id) [0x00000] 中:0
在 Pipedream.UI.Stage.CreateLayer (Pipedream.ComponentID id) [0x00000] 中:0

其实构造函数的代码是这样的:

Actually the code of the constructor looks like this:

internal StageLayer(ComponentID id)
    : base(id, ComponentLayer.System)
{
    base.Size = ApplicationBase.Instance.ScreenSize;
    ApplicationBase.Instance.PropertyChanged += HandlePropertyChanged;
}

该属性如下所示:

public virtual Vector2 Size
{
    get
    {
        return _Size;
    }
    set
    {
        Vector2 old = _Size;
        if (SetData(SizeDeclaration, value, ref _Size, Invalidate))
        {
            CompareUpdate(WidthDeclaration, _Size.X, old.X);
            CompareUpdate(HeightDeclaration, _Size.Y, old.Y);
        }
    }
}

好吧,Vector2 是一个结构体,不能为 null.这段代码也可以在桌面上完美运行.我想不出这段代码应该崩溃的任何原因,但它也不会在 iOS 模拟器上,仅在 iOS 设备上(我目前没有设备,所以我无法直接调试它).

Well the Vector2 is a struct and cannot be null. Also this code works perfectly on desktop. I can't think of any reason why this code should crash but it also does not on iOS simulator, only on iOS-device ( I currently have no device so i'm not able to debug it directly ).

我在调用这段代码之前启动了一些任务,但是它们使用自己的数据并且不能与当前数据冲突,即使这样也不应该有任何NullReferenceException.

事实证明,当应该调用 CompareUpdate 方法时会抛出异常.无论如何,我认为非虚拟通用方法不应该有任何问题?

It turns out that the exception is thrown when the CompareUpdate-method should be called. Anyway i thought that non virtual generic methods should not make any issues?

protected Boolean CompareUpdate<T>(DependencyProperty property, T newValue, T oldValue)
{
    if (!Object.Equals(newValue, oldValue))
    {
        ForceUpdate(property, newValue, oldValue);
        return true;
    }
    return false;
}

编辑 2

在更多的测试用例之后,我发现这可能是一个真正的编译器问题.以下测试失败:

Edit 2

After some more test cases i found out that that this might be a real compiler issue. The following test fails:

Log.Info(_Size.X.ToString()); // _Size is still a struct

除此之外:

System.NullReferenceException:未将对象引用设置为对象的实例
在 System.Single.ToString () [0x00000] 在/Developer/MonoTouch/Source/mono/mcs/class/corlib/System/Single.cs:260
在 Pipedream.UI.UIElement.set_Size (Vector2 value) [0x00031] in C:\WORK\00_PROJECTS\16 Pipedream\00_FRAMEWORK\trunk\Pipedream\UI\UIElement.cs:332

如果我将原始代码更改为以下代码也没有错误:

If i change the original code to the following there is also no error:

Vector2 old = _Size;
if (SetData(SizeDeclaration, value, ref _Size, Invalidate))
{
    CompareUpdate(WidthDeclaration, 0f, 0f);
    CompareUpdate(HeightDeclaration, 0f, 0f);
}

当我删除 SetData 方法时也会发生此错误,因此这不可能是错误原因.我已经检查了这个引用,所以堆栈似乎没问题,但是如果我尝试访问 _Sizes 变量 X 并尝试将它打印到控制台 NullReferenceException再次发生.

This error also occurs when i remove the SetData-method, so this can't be the error cause. I've checked the this reference so the stack seems to be ok, but if i try to access the _Sizes variable X and try to print it to the console the NullReferenceException occurs again.

推荐答案

事实证明这存在架构差异错误.Vector2[StructLayout(LayoutKind.Sequential, Pack = 1)] 行导致 Vector2 未对齐,这在某些架构中是非法的.

As it turns out this has an architecture difference bug. The [StructLayout(LayoutKind.Sequential, Pack = 1)] line of the Vector2 causes the Vector2 to be unaliagned which is illegal in some architectures.

暂时删除该行即可解决问题.

Removing the line for now removed the issue.

这篇关于Monotouch 在不可为空的对象上因 NullReferenceException 崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-21 01:51