Posted by: leppie | December 7, 2009

Calling an instance method in the CLR without an instance

A question came up how StackOverflow, blah.

I have heard about this behaviour being valid in C++, so I thought I would test it on the CLR.

.class Program
{
  .method static void  Main(string[] args)
  {
    .entrypoint
    .locals init ([0] class Program p)
    ldloc.0 // but wait, it's still null!
    call   instance void Program::Awesome()
    ret
  } 

  .method instance void Awesome()
  {
    ldstr      "Awesome!"
    call       void [mscorlib]System.Console::WriteLine(string)
    ret
  } 

  .method public specialname rtspecialname instance void  .ctor()
  {
    ldarg.0
    call       instance void [mscorlib]System.Object::.ctor()
    ret
  } 
} 

As you can see if you compile the program, “Awesome!” is printed.

Now run PEVerify. As you can see, perfect valid CLR code.

But how? And why wont in work in C#?

The C# compiler will in all cases (even weirdly, but probably for good reason) emit a callvirt instead of the call I used. This causes the runtime to perform a null check.

Secondly, the is no instance member access, so no references to ‘this’ need to be made.

Why is this like this? Not sure, but if I would guess, they left this specification loose, to allow for more flexibility in other languages.


Responses

  1. I guess these posts explains it – http://blogs.msdn.com/cbrumme/archive/2003/04/25/51377.aspx, http://blog.barrkel.com/2006/05/call-vs-callvirt-for-c-non-virtual.html,
    http://stackoverflow.com/questions/845657/why-is-the-c-compiler-emitting-a-callvirt-instruction-for-a-gettype-method-cal

    • Thanks for those links 🙂

      I did not really bother looking around 😦

  2. Hello,
    It has been a while since I have seen visible progress available for general public consumption. Will there be anymore work on this project (Ironscheme) this year (2010) ? Thank you. Good day.


Leave a comment

Categories