作为一个刚刚开始学习计算机调试的复杂性的人,我一生都无法理解如何读取 Windbg 中转储的堆栈文本。我不知道从哪里开始如何解释它们或如何去做。谁能为这个可怜的灵魂提供方向?

即(实际上我手头上唯一的转储)

>b69dd8f0 bfa1e255 016d2fc0 89efc000 00000040 nv4_disp+0x48b94

b69dd8f4 016d2fc0 89efc000 00000040 00000006 nv4_disp+0x49255

b69dd8f8 89efc000 00000040 00000006 bfa1dcc0 0x16d2fc0

b69dd8fc 00000000 00000006 bfa1dcc0 e1e71018 0x89efc000

我知道问题与 Nvidia 显示驱动程序有关,但我想知道如何实际读取堆栈(例如,b69dd8f4 是什么?):-[

有帮助吗?

解决方案

首先,您需要配置正确的符号。这些符号将允许您将内存地址与函数名称相匹配。为此,您必须在计算机中创建一个本地文件夹,在其中存储符号的本地缓存(例如:C:\符号)。然后您需要指定符号服务器路径。要执行此操作,只需转到:文件 > 符号文件路径和类型:

SRV*c:\symbols*http://msdl.microsoft.com/download/symbols

您可以找到有关如何正确配置符号的更多信息 这里.

正确配置符号服务器后,您可以从以下位置打开小型转储:文件 > 打开故障转储。

打开小型转储后,它将在命令行左侧显示生成转储时正在执行的线程。如果您想查看该线程正在执行什么,请输入:

kpn 200

第一次执行它可能需要一些时间,因为它必须第一次下载必要的公共 Microsoft 相关符号。下载完所有符号后,您将得到类似以下内容的信息:

01 MODULE!CLASS.FUNCTIONNAME1(...)
02 MODULE!CLASS.FUNCTIONNAME2(...)
03 MODULE!CLASS.FUNCTIONNAME3(...)
04 MODULE!CLASS.FUNCTIONNAME4(...)

在哪里:

  • 第一个数字:表示帧数
  • 模块:包含代码的 DLL
  • 班级:(仅适用于 C++ 代码)将显示包含该代码的类
  • 功能名称:被调用的方法。如果您有正确的符号,您还将看到参数。

您可能还会看到类似的内容

01 MODULE!+989823

这表明您没有该 DLL 的正确符号,因此您只能看到方法偏移量。

那么,什么是调用堆栈?

想象一下你有这样的代码:

void main()
{
  method1();
}

void method1()
{
  method2();
}

int method2()
{
  return 20/0;
}

在此代码中,method2 基本上会抛出异常,因为我们试图除以 0,这将导致进程崩溃。如果发生这种情况时我们得到了小型转储,我们将看到以下调用堆栈:

01 MYDLL!method2()
02 MYDLL!method1()
03 MYDLL!main()

您可以从这个调用堆栈中得知,“main”调用了“method1”,然后调用了“method2”,但失败了。

在你的情况下,你有这个调用堆栈(我猜这是运行“kb”命令的结果)

b69dd8f0 bfa1e255 016d2fc0 89efc000 00000040 nv4_disp+0x48b94
b69dd8f4 016d2fc0 89efc000 00000040 00000006 nv4_disp+0x49255
b69dd8f8 89efc000 00000040 00000006 bfa1dcc0 0x16d2fc0
b69dd8fc 00000000 00000006 bfa1dcc0 e1e71018 0x89efc000

第一列表示子帧指针,第二列表示正在执行的方法的返回地址,接下来的三列显示传递给该方法的前3个参数,最后一部分是DLL名称(nv4_disp)以及正在执行的方法的偏移量(+0x48b94)。由于您没有符号,因此您无法看到方法名称。我怀疑 NVIDIA 是否向公众提供对其符号的访问,因此我猜您无法从这里获得太多信息。

我建议您运行“kpn 200”。这将向您显示完整的调用堆栈,并且您也许能够看到导致此崩溃的方法的起源(如果它是 Microsoft DLL,您应该在我为您提供的步骤中拥有正确的符号)。

至少你知道它与 NVIDIA bug 有关;-) 尝试将此驱动程序的 DLL 升级到最新版本。

如果您想了解有关 WinDBG 调试的更多信息,我推荐以下链接:

其他提示

这里有一个关于解释堆栈跟踪的非常好的教程:

http://www.codeproject.com/KB/debug/cdbntsd2.aspx

然而,即使有了这样的教程,如果没有可用/加载的正确符号,解释堆栈转储也可能非常困难(或几乎不可能)。

包含您尝试读取的堆栈的示例可能会有所帮助。一个好的技巧是确保堆栈中显示的所有模块都有正确的调试符号。这包括操作系统中模块的符号,微软已经公开了他们的符号服务器。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top