Can Interlocked.CompareExchange throw NullReferenceException?

后端 未结 2 1490
春和景丽
春和景丽 2021-01-19 00:23

From https://msdn.microsoft.com/en-us/library/bb297966(v=vs.110).aspx

[ComVisibleAttribute(false)]
public static T CompareExchange(
    ref T locati         


        
2条回答
  •  情歌与酒
    2021-01-19 00:38

    As the other answer says, it's perfectly OK to have your variable contain null -- it's about the reference to the variable being null, and that can't happen in C#, or most other managed languages for that matter.

    That said, you can make Interlocked.CompareExchange throw a NullReferenceException by working directly from IL. But even there you have to get tricky if you want to remain in the realm of managed, verifiable code:

      .method private hidebysig static void  Main(string[] args) cil managed
      {
        .entrypoint
        .maxstack  3
        .locals init ([0] int32& x)  // x is initialized to null
        ldloc.0
        ldc.i4.1
        ldc.i4.2
        call  int32 [mscorlib]System.Threading.Interlocked::CompareExchange(
          int32&, int32, int32)
        pop
        ret
      }
    

    This code will pass verification, but it will throw a NullReferenceException at runtime. The stack trace will not actually show Interlocked.CompareExchange, since the JIT compiler inlines it to a single lock cmpxchg instruction.

    As @Sean correctly pointed out, this should not really justify the documentation saying that the method may throw a NullReferenceException, because this technique can be used to break any function taking a ref or out parameter. For example, Int32.TryParse does not document that it can throw a NRE if "the address of result is null", nor would we expect it to. Managed code is implicitly expected to be well-behaved when it comes to references.

提交回复
热议问题