3

在 Visual Studio 2012 中,我正在使用调试启动应用程序。我打开一些屏幕,然后关闭它。此时,当我查看调用堆栈时,我可以看到我的应用程序的起点、一些打开/关闭屏幕的方法,以及许多不是来自我的应用程序的(外部)调用。我注意到的是,我的应用程序中的许多调用都没有列出,尽管它们已被执行。

我在我的应用程序中放置了一个断点。当应用程序遇到断点时,我开始使用 F11 单步执行代码。基本上它所做的是,它从循环中调用 SomeMethod (断点设置在循环中)。

当我使用 F11 进入 SomeMethod 时,我看到 SomeMethod 在调用堆栈中列出,但是如果我按 F5,然后再次打断点(在循环中),再查看调用堆栈,SomeMethod 没有列出任何更多的。

那么,调用堆栈如何决定在其中显示哪些方法呢?我们如何才能获得已执行的方法的完整列表?

4

5 回答 5

3

调用堆栈不是已调用方法的列表,而是已调用但未返回的方法列表。

让我解释

我将首先给出一个函数调用的简单示例。在运行程序时调用该函数。为此,它将参数和自身的位置推送到堆栈上。(现在位于堆栈的顶部)。然后它调用函数,该函数将指令指针跳转到该函数的代码所在的位置。该函数将其参数从堆栈中拉出(它刚刚被调用,因此它知道它们必须在堆栈的顶部)并运行它的本地代码。完成后,它将返回地址从堆栈中拉出,并使用它将指令指针返回到调用此函数的位置。

现在在更复杂的情况下,任何函数都可以调用任何其他函数——它的工作方式完全相同,但现在堆栈将包含在最近调用函数底部调用的第一个函数。因为您总是从堆栈的顶部获取,所以您将始终返回到上次调用的位置。

好的,所以在调试器中查看调用堆栈时,您将看到在您在程序中所在位置之前进行的所有函数调用。在某些时候,代码将返回到堆栈中列出的那些位置。但是,如果一个函数调用已经从它返回,它将不再在堆栈上,当该函数返回时,它已经从堆栈中弹出。

于 2013-10-11T17:11:33.947 回答
2

调用堆栈仅显示特定线程当前“正在进行”(它们尚未退出)的方法。堆栈不包括已完成的方法。

找出运行(或未运行)哪些方法的最简单方法是使用分析器。在 Visual Studio 中,它称为“性能分析”(位于“分析”菜单下)。

如果您是分析新手,我建议您使用“性能向导”(也在分析菜单上)。选择“Instrumentation”作为分析方法,因为这将为您提供函数调用计数(采样可能会错过不需要太多时间的方法调用)。

还值得一提的是,分析器不会给出方法调用的顺序。它只会计算它们。如果您需要知道方法调用的顺序,则需要手动跟踪(通过在每个方法的开头和/或结尾添加代码来记录调用)。

于 2013-10-11T17:12:13.663 回答
2

调用堆栈不显示先前已执行的方法。相反,它们显示了正在执行的方法调用树/堆栈/层次结构。第一种方法是您当前使用的方法 - 通常是您设置断点或单步使用调试器的地方。

您可以通过使用“Step out”命令看到这一点 - 这会将您直接跳转到调用堆栈中的下一个方法。

于 2013-10-11T17:12:49.900 回答
0

我认为您对调用堆栈的实际含义有误解。每当一个方法调用另一个方法时,它在旧方法中的地址就会被压入堆栈。一旦它返回到该方法,它就会从堆栈中弹出并且将不再被看到。

它不是所有已调用方法的记录,而是当前执行块完成时执行将返回到的位置的列表。

于 2013-10-11T17:12:00.117 回答
0

调用堆栈是一种堆栈数据结构,用于存储有关活动子例程的信息。当方法完成时,它不再被认为是活动的,因此不会显示在调用堆栈上。基本上,您可以看到的调用堆栈是方法调用的当前路径,以到达断点被击中的位置。

于 2013-10-11T17:12:14.717 回答