在调试版本和发布版本中获取有问题代码的行号

3

我的理解是,在调试版本的崩溃转储中,您可以获得堆栈跟踪的行号,而在发布版本中则不会。为了尝试这一点,我创建了一个非常简单的应用程序来导致崩溃。

class Program  
{  
    static void Main(string[] args)  
    {  
        Console.WriteLine("Press any key to continue");  
        Console.ReadKey();  
        TestMe(null);  
    }  


    static void TestMe(MyClass c)  
    {  
        Console.WriteLine(c.Field);  
    }  
}  

class MyClass  
{  
    public string Field { get; set; }  
}  

我创建了一个调试版本和一个发布版本,运行它们并通过ADPlus捕获了崩溃转储。以下是每个版本的堆栈跟踪。正如您所看到的,在两个版本中我都得到了行号。显然不同之处在于发布版本没有报告对TestMe方法的调用。有什么想法吗?我是否需要在两种情况下添加应用程序pdb文件的符号路径。 调试版本
0:000> !CLRStack  
OS Thread Id: 0x2398 (0)  
Child SP IP       Call Site  
001eee74 003400db ConsoleApplication1.Program.TestMe(ConsoleApplication1.MyClass)*** WARNING: Unable to verify checksum for ConsoleApplication1.exe  
 [c:\ConsoleApplication1\ConsoleApplication1\Program.cs @ 20]  
001eee84 003400a5 ConsoleApplication1.Program.Main(System.String[]) [c:\ConsoleApplication1\ConsoleApplication1\Program.cs @ 14]  
001ef0c8 6ccb21bb [GCFrame: 001ef0c8] 

发布构建

0:000> !CLRStack  
OS Thread Id: 0x2e40 (0)  
Child SP IP       Call Site  
003bf5f8 772af8c1 [GCFrame: 003bf5f8] Unknown  
003bf3b4 002b0098 ConsoleApplication1.Program.Main(System.String[])*** WARNING: Unable to verify checksum for ConsoleApplication1.exe  
 [c:\ConsoleApplication1\ConsoleApplication1\Program.cs @ 14]  
003bf5f8 6ccb21bb [GCFrame: 003bf5f8]   

可能是当CLR可以将方法内联时?的重复问题。 - Hans Passant
1个回答

2
在发布版本中,JIT编译器无疑会内联方法调用 - 这就是为什么行号不同的原因。

所以发布版本也会在堆栈跟踪中报告行号?我以为只有在调试版本中才会发生这种情况。 - palm snow
@palmsnow:我相信在调试版本中有比发布版本更多的调试信息,显然你仍然需要有pdb文件可用,但如果它给出了行号,那就很有帮助 :)(在许多使用发布版本的地方,PDB并没有被提供,这可能导致了混淆。) - Jon Skeet
尽管您可能是正确的,即JIT编译器将内联该调用,但最顶层的堆栈框架位于完全不同的地址,因此我怀疑这与内联无关。我认为该地址指向SEH代码。 - Brian Rasmussen
@Jon,当您说调试版本具有更多的调试信息时,能否请您提供一些具体的例子(或链接),说明在调试版本中我可以得到什么样的信息,在发布版本中无法获得? - palm snow
1
@palmsnow:调试版本不像发布版本那样被积极优化,因此您将能够轻松找到本地变量和参数。此外,内联调用会使发布版本的堆栈跟踪读起来有些复杂。 - Brian Rasmussen
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接