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

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

这可能吗?

编辑:

无论它是否出现在我的问题中,真的是在问是否有一种简单/内置的方法来做到这一点。真的,这只是一个权宜之计,直到我可以对系统的其他部分进行重大更改。谢谢你的好答案。看到他们之后,我想我会等。 . . :)

最佳答案

你想在这里实现什么?

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

如果您想做的只是在程序 session 中组合“唯一”调用路径,请继续:我肯定会使用 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

当然,对于移动分配器来说,在对象的整个生命周期内保证一个恒定的散列会稍微复杂一些,但你明白了:每个运行时都会生成不同的散列,完成的分配量将改变 future 的默认散列码相同的对象。

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

即使您通过提供适当的确定性哈希函数修复了该部分,您也需要每个堆栈帧都是“可识别”类型。情况可能并非如此。如果您使用类似于 LINQ、匿名类型、静态构造函数、委托(delegate)的任何东西,当然不会;各种各样的事情可能是将堆栈帧与(匿名)助手类型的堆栈帧交错,甚至是 JIT 编译器发明的性能蹦床以优化尾递归、大型切换跳转表或在多个重载之间共享代码。

要点:堆栈分析很难:如果您要进行它,您绝对应该使用正确的 API。

结论:

一定要有一个球。但听从建议
  • 您的要求是非标准的(由不支持它的运行时库下划线);这通常表明:您正在解决一个独特的问题(但重新考虑选择的工具?)或者您正在以错误的方式解决它
  • 通过生成带有一些手写模拟代码的流程图,而不是尝试连接到 CLR VM
  • ,您或许可以获得更多信息
  • 如果您打算这样做,请使用正确的 API(可能是探查器 API,因为采样探查器将准确保存此内容:堆栈“指纹”每条指令)
  • 如果您确实必须通过检测代码来实现,请考虑使用 AOP
  • 关于c# - 获取调用对象的哈希码?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6103034/

    10-12 12:43
    查看更多