代码之家  ›  专栏  ›  技术社区  ›  Cecil Has a Name

如何获取stackframe的执行对象?

  •  11
  • Cecil Has a Name  · 技术社区  · 15 年前

    使用反射时,可以使用System.Diagnostics.StackTrace获得调用堆栈(除此之外,由于JIT优化,调用堆栈可能是粗略的近似值),并检查包含的StackFrame对象。

    如何获取对堆栈帧中的方法正在其上执行的对象(this指针)的引用?

    我知道我可以通过调用stack frame对象上的GetMethod()来获得MethodBase,但我要寻找的是与GetObject()类似的东西(如果方法是静态的,它自然会返回null)。似乎堆栈帧对象只能查询静态确定的信息,如方法信息、原始文件等。

    VS调试器知道(尽管它可能使用另一种获取调用堆栈跟踪的方法),因为可以双击调用堆栈窗口中的任何堆栈帧并查看局部变量和类字段的值。

    澄清一下:我想要 对象

    3 回复  |  直到 15 年前
        1
  •  7
  •   Wai Ha Lee captain-yossarian from Ukraine    8 年前

    我很确定这是不可能的。原因如下:

    1. 这可能会破坏类型安全性,因为任何人都可以查找帧,获取对象,而不管他们在哪个AppDomain\线程上执行或拥有什么权限。

    2. 这个 this 对于实例方法,这当然意味着您需要访问所有方法参数才能获得 StackFrame (不支持)

    通过使用 unsafe

    顺便说一句,您可以想象实例方法在编译后与C#3.0扩展方法类似,它们得到 指针作为它们的第一个参数。

        2
  •  3
  •   avpaderno    12 年前

    有可能获得参考资料 thiscall 对象,但不能仅使用.NET代码。必须包含本机代码。即使使用动态类和System.Relation.Emit命名空间,NET也没有工具来访问另一个方法计算堆栈和参数。

    另一方面,若你们反汇编你们的.NET方法,你们可以看到这个引用根本并没有传递到物理堆栈上。 Thiscall 引用存储在 ECX ( RCX 对于x64),请改为注册。所以,从您的方法到您希望从中获得的方法,可以在堆栈上爬升 对象然后在该方法的机器代码中查找将寄存器ECX(RCX)保存在堆栈中的指令,并从该引用所在的指令相对地址获取。

    当然,攀爬的方法在x32和x64应用中有很大的不同。要生成这样的函数,您不仅必须使用C#,还必须使用汇编代码,并记住x64下不允许使用内联汇编程序;它必须是一个完整的汇编模块。

        3
  •  0
  •   Fredrik Mörk    15 年前

    StackTrace trace = new StackTrace();    
    Type methodOwner = trace.GetFrame(0).GetMethod().DeclaringType;