发生异常时如何获取IL指令偏移量?

How to get IL instruction offset when exception happens?

我想在发生异常时获取 IL 指令偏移量(从方法开始)。

例如我有对象初始值设定项:

var obj = new SomeObject {
   F1 = something.A,
   F2 = something.B,
   F3 = something.C,
   F4 = something2.A,
   F5 = something.D
};

如果 something2 将是 null - 将抛出异常。

异常堆栈跟踪将指向第一行:

var obj = new SomeObject {

我能否获得问题对象的准确 IL 代码偏移量?

在这个例子中,我想得到这条指令的偏移量:

callvirt instance void SomeClass2::get_A(class SomeClass2)

更新:已发布的答案 here(通过 PDB)在这种情况下不起作用,因为线会指向同一个地方。

不确定它是否能准确解决您的问题,但如果您使用 ildasm 获取程序集的 IL 列表,那么您可以重构程序集并使用以下方法生成新的 .pdb:ilasm /PDB /DEBUG ... (程序集应该在功能上等同于原始程序集,尽管不是逐字节相同)。

这个过程的有趣之处在于生成的 .pdb 将 IL 列表视为 "source",因此只要您的 IDE 可以找到 .pdb 和 IL 列表,您可以像单步执行普通 C# 一样逐条执行 IL 指令,并且您还会看到它们发生的 IL 指令异常(即使对于 属性 初始值设定项,如您的示例)。

如果遇到异常中断,您可以在监视 window 中创建一个 StackTrace 对象,将异常传递到其构造函数并在第一帧调用 GetILOffset() (类似于 new StackTrace($exception).GetFrame(0).GetILOffset() IIRC)。

话虽如此,JIT 可能最终会将所有为该语句生成的本机代码映射到相同的 IL 偏移量,在这种情况下,除了分解该语句之外,您无能为力。