我们使用 System.Reflection.Emit 在运行时从源代码生成代码(是的 - 就像在编译器中一样)。我们使用 MarkSequencePoint 等向 ILGenerator 提供正确的符号信息,并启用 AssemblyBuilder 上的所有调试标志。程序集在编译它的同一进程中保存在内存中并直接执行。
当使用 Visual Studio 调试器单步调试动态生成代码的源代码时,它实际上工作得很好,而且 Visual Studio 似乎完全知道代码来自文件和行号的位置。
但是 - 当生成的代码抛出异常时,System.Exception 对象包含完全错误的堆栈跟踪。它们指向其他(有效但错误的)文件和行号。它正确地获取了类和方法名,但指向的文件和行号与异常实际来自的代码路径无关。
指向的文件是如此无关,似乎无法链接到内联或优化。我能发现的唯一模式是它似乎被某些文件抵消了(在构建程序集的源文件的虚构字母顺序列表中)。然而,这种模式并不是 100% 一致的,这与问题的根源有关似乎是不合理的。
如果我从异常构造一个 System.Diagnostics.Debug 对象,它包含相同的错误信息。
我假设 .NET 运行时使用与调试器用于单步执行代码的元数据相同的元数据来构造异常堆栈跟踪,在这种情况下,这种行为真的很奇怪。
我试图找出在处理动态内存程序集时这是否是 .NET 中的一个已知错误,或者是否有人在其他领域看到过类似的问题。