作为一个刚刚开始学习复杂的计算机调试的人,对于我的生活,我无法理解如何阅读 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:\symbols)。然后您需要指定符号服务器路径。为此,只需转到:文件 > 符号文件路径并键入:
SRV*c:\symbols*http://msdl.microsoft.com/download/symbols
您可以找到更多关于如何正确配置符号的信息 here .
正确配置符号服务器后,您可以从以下位置打开小型转储:文件 > 打开故障转储。
打开 minidump 后,它将在命令行左侧显示生成转储时正在执行的线程。如果你想看看这个线程正在执行什么类型:
kpn 200
第一次执行它可能需要一些时间,因为它必须第一次下载必要的公共(public) Microsoft 相关符号。下载所有符号后,您将获得如下信息:
01 MODULE!CLASS.FUNCTIONNAME1(...)
02 MODULE!CLASS.FUNCTIONNAME2(...)
03 MODULE!CLASS.FUNCTIONNAME3(...)
04 MODULE!CLASS.FUNCTIONNAME4(...)
在哪里:
您可能还会看到类似
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 错误有关 ;-) 尝试将此驱动程序的 DLL 升级到最新版本。
如果您想了解有关 WinDBG 调试的更多信息,我推荐以下链接:
关于multithreading - 解释 Windows Minidump 中的堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77887/