获取调用对象的HashCode?

时间:2011-05-23 21:05:38

标签: c# reflection

这可能是重复的,但我没有看到这个确切的问题或类似的问题/答案的日期比.Net 4的发布日期更新。

我正在寻找一个临时的hack,它允许我查看调用堆栈并获取堆栈中的所有调用对象(不是方法,但是包含方法的实例)。最终我需要他们的哈希码。

这可能吗?

修改

无论是否在我的问题中遇到过,都在问是否有一种简单/内置的方式来做到这一点。真的,只是一个止损修复,直到我可以对系统的其他部分进行重大更改。谢谢你的答案。看到它们之后,我想我会等。 。 。 :)

4 个答案:

答案 0 :(得分:5)

你想在这里实现什么?

看看我一个月前回答的类似问题:How to get current value of EIP in managed code?。你可能会从中获得灵感。或者你可能认为它太难看了(后者为+1)。

如果您只想在程序会话中组装“唯一”调用路径,请继续:我非常确定使用AOP编织器并线程本地存储。这样做不会太难。

警告1:哈希对通用.NET对象

不是很有用

随机对象的哈希码可能会随着它在堆上的位置而变化。供参考:在MONO上,在禁用移动堆分配器的情况下,Object :: GetHash就是这个相当庞大的代码块(mono/metadata/monitor.c

#else
/*
 * Wang's address-based hash function:
 *   http://www.concentric.net/~Ttwang/tech/addrhash.htm
 */
    return (GPOINTER_TO_UINT (obj) >> MONO_OBJECT_ALIGNMENT_SHIFT) * 2654435761u;
#endif

当然,对于移动分配器来说,事情稍微复杂一点,以保证在对象的生命周期内保持一个恒定的散列,但是你得到了重点:每个运行时将生成不同的散列,并且完成的分配量将改变未来相同对象的默认哈希码。

警告2:你的堆栈将包含外星人框架

即使您通过提供适当的确定性散列函数来修复该部分,您也需要每个堆栈帧都是“可重新排列”的类型。情况可能并非如此。当然不是你使用类似于LINQ,匿名类型,静态构造函数,委托的东西;所有类型的东西都可以将堆栈帧与(匿名)辅助类型交织,甚至是JIT编译器发明的性能蹦床,以优化尾递归,大型切换跳转表或多个重载之间的共享代码。

外卖:堆栈分析很难:如果要进行堆栈分析,你肯定应该使用正确的API。

结论:

一定要有一个球。但听从了建议

  1. 您的要求是非标准的(由不支持它的运行时库加下划线);这通常表明:您正在解决一个独特的问题(但重新考虑所选择的工具?)或者您正在以错误的方式解决问题
  2. 您可以通过生成带有一些手写模拟代码的流程图而不是尝试挂钩到CLR VM来获取更多信息
  3. 如果您要这样做,请使用正确的API(可能是探查器API,因为采样分析器将完全保存:堆栈'指纹'每个如此多的指令)
  4. 如果您真的必须通过检测代码来实现,请考虑使用AOP

答案 1 :(得分:1)

您可以通过创建StackTrace类的实例并检查其中的StackFrame对象来获取调用堆栈。查看成员列表,但这似乎并没有揭示实例,只是类和方法。

答案 2 :(得分:1)

这仅适用于非托管API,特别是CLR分析API。除了它用于实现分析和调试工具之外,我知道它没有。你必须谷歌并且习惯于燃烧1周才能投入生产。如果可能的话,放弃你的计划并寻找替代方案。告诉我们你想做什么,我们可以提供帮助!

答案 3 :(得分:0)