2

考虑以下 C# 代码:

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" });
    }
}

当我在 Visual Studio 2008 或 Visual Studio 2008 中运行它并命中我在“打印”方法中放置的断点时,我在调用堆栈窗口中得到以下信息:

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

[本机到托管转换]

[管理到本地转换]

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

为什么没有RuntimeMethodInfo.Invoke出现在我的调用堆栈中?毕竟,它是一种托管方法,那么为什么我看不到我所期望的呢?

另外,一般来说,这里的规则是什么?我的调用堆栈中可能会缺少哪些托管方法?

4

1 回答 1

1

原因是该方法实际上不是托管方法。RunTimeMethodInfo.Invoke最终将解析RuntimeMethodHandle._InvokeMethodFast为标记为MethodImplOptions.InternalCall. 这意味着调用实际上是直接在CLR中作为帮助程序实现的。

关于不会出现在调用堆栈中的一般规则:

  • 如果您已Just My Code启用(这是默认设置),几乎所有您未编写的内容都会显示[External Code]在调用堆栈上。
  • 如果您只调试托管,那么您可能最终会在调用堆栈上看到很多Native to Managed和转换。Managed to Native
  • 在处理内部实现的方法时,您还会在调用堆栈上看到一些模糊性。
  • 我不确定 的确切规则DebuggerHidden,尤其是与“仅我的代码”方法结合使用时,但我不必期望它们出现在调用堆栈上。

如果您想看到原始调用堆栈的所有荣耀,那么您需要执行以下操作。

  • 在启用托管和本机调试的情况下进行调试
  • 禁用Just My Code
于 2011-07-10T21:13:25.167 回答