3

情况

我正在使用 ILGenerator 生成包装器。我使用Object.Equals(Object, Object)用于实现包装器字段的相等比较。调试器抛出NullReferenceException带有以下堆栈跟踪的 a。

at System.Object.Equals(Object objA, Object objB)
at HIDDEN.StateTransitionWrapper.op_Equality(StateTransitionWrapper , StateTransitionWrapper )
at HIDDEN.StateTransitionWrapper.Equals(Object )
at System.Object.Equals(Object objA, Object objB)
at HIDDEN.StationEventCompositeWrapper.op_Equality(StationEventCompositeWrapper , StationEventCompositeWrapper )
at HIDDEN.StationEventCompositeWrapper.Equals(Object )
at System.Object.Equals(Object objA, Object objB)
at HIDDEN.CompareResult..ctor(Object object0, Object object1, String fieldName) 
....

Object.Equals(Object, Object) - 反汇编

public static bool Equals(object objA, object objB)
{
    return objA == objB || (objA != null && objB != null && objA.Equals(objB));
}

正如您在反汇编中看到的那样,不可能NullReferenceException发生任何事情,因为它不会到达方法调用所在的部分。

可能的问题

正如我所说,漏洞代码是使用 ILGenerator 生成的,我认为这可能是错误的唯一可能来源。调用者内部只有值类型,因此对象甚至不可能为空。

调用 IL 代码

IL_0040: ldarg.0
IL_0041: call instance valuetype [HIDDEN]HIDDEN.StationStateType HIDDEN.StateTransitionWrapper::get_StationState()
IL_0046: box [mscorlib]System.Object
IL_004b: ldarg.1
IL_004c: call instance valuetype [HIDDEN]HIDDEN.StationStateType HIDDEN.StateTransitionWrapper::get_StationState()
IL_0051: box [mscorlib]System.Object
IL_0056: call bool [mscorlib]System.Object::Equals(object, object)
4

2 回答 2

3

指令不应该box指定您要装箱的类型吗?

例如,您不应该使用...

box System.Int32  // or whatever

...而不是...

box System.Object
于 2012-02-28T17:05:29.100 回答
2

box typeTok操作码(ECMA-355 Partition III,第 4.2 节)从堆栈中获取val并将其转换为obj。如果typeTok是引用类型,则box指令将val未 更改[强调添加] 返回为obj。另一方面,当typeTok是值类型(至少是不可为空的)时,box会创建一个新对象并将数据从val复制到新对象中。

正如@LukeH 指出的那样,上面的 IL 在box [mscorlib]System.Object应该使用box [HIDDEN]HIDDEN.StationStateType. 后者仍将返回object对调用有效的Object.Equals(Object, Object)。我相信当前调用返回了一个导致NullReferenceException.

于 2012-02-28T20:19:34.123 回答