What happens when we have code as bellow
class B
{
public virtual void Virt(){
Console.WriteLine("Base::Virt");
}
}
class Program
{
static void Main(string[] args){
B b = null;
b.Virt(); // throws System.NullReferenceException
}
}
Obviously we have a null reference exception being thrown. If you see the IL the call looks like
L_0000: nop
L_0001: ldnull
L_0002: stloc.0
L_0003: ldloc.0
L_0004: callvirt instance void ConsoleApplication1.B::Virt()
L_0009: nop
L_000a: ret
So in effect you'd expect the jitter to generate the following kind of code (in processor instruction)
if (b == null)
throw new NullReferenceException
else
b->Virt() // actually call safely using the this pointer
However, generating null checks for every call is going to lead to code bloat. So to work around this on some platforms (e.g. .NETCF on WinCE 6.0 and above) it uses the following approach
- Hook up native access violation exception (WinCE 6.0 supports this) to a method in the execution engine (EE)
- Do not generate any null checking and directly generate calls through references
- In case the reference is null then a native AV (access violation is raised as invalid 0 address is accessed) and the hook method is called
- At this point the EE checks to see if the source of the access violation (native code) is inside Jitted code block. If yes it creates the managed NullRefenceException and propagates it up the call chain.
- If it's outside then obviously it's either CLR itself or some other native component is crashing and it has nothing to do about it..
No comments:
Post a Comment