动态代码中的异常堆栈跟踪中的文件路径和行号错误

Duc*_*ers 12 .net c# cil stack-trace assemblybuilder

我们正在使用System.Reflection.Emit在源代码中从源代码生成代码(是的 - 在编译器中).我们使用MarkSequencePoint等向ILGenerator提供正确的符号信息,并启用AssemblyBuilder上的所有调试标志.程序集在编译它的同一进程中保存在内存中,并直接执行.

当使用Visual Studio调试器逐步完成动态生成的代码的源代码时,它实际上工作得很好,并且Visual Studio似乎完全了解代码来自文件和行号的位置.

无论其-当异常被抛出生成的代码,该System.Exception的对象包含堆栈是完全错误的痕迹.它们指向其他(有效但错误的)文件和行号.它获取了类和方法名称,但指向的文件和行号与实例异常的代码路径无关.

指向的文件是如此无关,似乎无法链接到内联或优化.我能看到的唯一模式是它似乎被一些文件所抵消(在一个假想的按字母顺序排序的源文件列表中,汇编是从中构建的).但是,这种模式并非100%一致,而且这与问题的根源相关联似乎是不合理的.

如果我从Exception构造一个System.Diagnostics.Debug对象,它包含相同的错误信息.

我假设.NET运行时使用相同的元数据来构造Exception堆栈跟踪,因为调试器用于单步执行代码,在这种情况下,这种行为非常奇怪.

我试图在处理动态内存中的程序集时,或者如果有人在其他方面遇到过类似的问题,那么这是否是.NET中的一个已知错误.

Duc*_*ers 2

好吧,我无法找出导致问题的原因,也无法弄清楚如何使 .NET 正常运行,但至少我能够找到一种可能也适用于遇到相同问题的其他人的解决方法。

  1. 当我生成 CIL 字节码时,我正在构建一个单独的数据库,它将方法名称(完整路径)和 IL 偏移量映射回原始文件名和行号。

  2. 当捕获异常时,我检查堆栈跟踪并仅使用堆栈帧对象中的GetMethod()和信息。GetILOffset()来自 CLR 的信息恰好是正确的,即使 和GetFileName()GetFileLineNumber()错误的。

  3. 然后,对于每个堆栈帧,我使用从异常中检索到的方法名称和 IL 偏移量来查找生成的数据库,以确定我拥有相关信息的每个堆栈帧的实际文件名和行号。

  4. 我在数据库中找不到相关信息的帧通常是预编译的 .NET 模块中的堆栈帧,从 CLR 检索到的信息实际上是正确的。对于这些框架,我直接在堆栈框架上使用GetFileName()and 。GetFileLineNumber()