Search code examples
c#visual-studiodebuggingvisual-studio-debugging

Why doesn't RuntimeMethodInfo.Invoke show up on my Visual Studio debugger callstack?


Consider the following C# code:

class Program
{
    static public void Print(string toPrint)
    {
        Console.WriteLine(toPrint);
    }

    static void Main(string[] args)
    {
        Type program = typeof(Program);            
        MethodInfo methodInfo = program.GetMethod("Print", BindingFlags.Static | BindingFlags.Public);
        methodInfo.Invoke(null, new object[] { "a" });
    }
}

When I run it in either Visual Studio 2008 or Visual Studio 2008 and hit a breakpoint I put inside the "Print" method, I get the following in the callstack window:

ConsoleApplication4.exe!ConsoleApplication4.Program.Print(string toPrint)

[Native to Managed Transition]

[Managed to Native Transition]

ConsoleApplication4.exe!ConsoleApplication4.Program.Main(string[] args)

Why doesn't RuntimeMethodInfo.Invoke show up in my callstack? It is a managed method, after all, so why don't I see it as I would expect?

Also, in general, what are the rules here? Which managed methods can I expect to be missing from my callstack?


Solution

  • The reason is that the method isn't actually a managed method. RunTimeMethodInfo.Invoke will eventually resolve down to RuntimeMethodHandle._InvokeMethodFast which is marked as an MethodImplOptions.InternalCall. This means the call is actually implemented as a helper directly in the CLR.

    In terms of general rules for what won't show up in your call stack:

    • If you have Just My Code enabled (which is the default) pretty much anything you didn't write will show up as [External Code] on the call stack.
    • If you are debugging managed only then you'll probably end up seeing a lot of Native to Managed and Managed to Native transitions on the call stack.
    • When dealing with internally implemented methods, you'll also see a bit of fuzziness on the call stack.
    • I'm not sure on the exact rules for DebuggerHidden, especially when combined with 'just my code' methods, but I wouldn't necessary expect them to show up on the call stack.

    If you want to see the raw call stack in all of its glory then you'll need to do the following.

    • Debug with both managed and native debugging enabled
    • Disable Just My Code