When you debug through some managed code at the assembly level, you’ll find a whole lot of seemingly pointless instructions that perform a comparison but ignore the result. What’s the point of comparing two values if you don’t care what the result is?
In C++, invoking an instance method on a NULL
pointer results in undefined behavior. In other words, if you do it, the compiler is allowed to do anything it wants. And what most compilers do is, um, nothing. They don’t take any special steps if the this
pointer is NULL
; they just generate code on the assumption that it isn’t. In practice, this often means that everything seems to run just fine until you access a member variables or call a virtual functions, and then you crash.
The C# language, by comparison, is quite explicit about what happens if you invoke an instance method on a null
object reference:
The value of
E
is checked to be valid. If the value ofE
is null, aSystem.NullReferenceException
is thrown and no further steps are executed.
The null reference exception must be thrown before the method can be called. That’s what the strange cmp [ecx], ecx
comparison is for.¹ The compiler doesn’t actually care what the result of the comparison is; it just wants to raise an exception if ecx
is null. If ecx
is null, the attempt to dereference it (in order to perform the comparison) will raise an access violation, which the runtime inspects and turns into a NullReferenceException
.
The test is usually against the ecx
register since the CLR happens to use² the fastcall
calling convention, which for instance methods passes the this
pointer in the ecx
register. The pointer the compiler wants to test is going to wind up in the ecx
register sooner or later,³ so it’s not surprising that the test, when it happens, is made against the ecx
register.
Nitpicker’s Corner
¹Although this statement is written as if it were a fact, it is actually my interpretation based on observation and thinking about how language features are implemented. It is not an official position of the CLR team nor Microsoft Corporation, and that interpretation may ultimately prove incorrect.
²”Happens to use” means that this is an implementation detail, not a contractual guarantee.¹
³Unless the call is optimized. For example, the function might be inlined.
0 comments