为什么我不能使用Windbg“!DumpHeap -stat”命令调查转储文件?

时间:2018-07-12 12:15:07

标签: clr windbg sos

首先,我是不同.NET平台上的新手。

我正在尝试使用Windbg调查托管.Net应用程序的转储(我不知道版本)。

为此,我想启动!DumpHeap -stat命令。
最初,这不起作用,因为未加载sos

0:000> !DumpHeap -stat
No export DumpHeap found
0:000> .load sos

但是,似乎还有另一个问题:

0:000> !DumpHeap -stat
The garbage collector data structures are not in a valid state for traversal.
It is either in the "plan phase," where objects are being moved around, or
we are at the initialization or shutdown of the gc heap. Commands related to 
displaying, finding or traversing objects as well as gc heap segments may not 
work properly. !dumpheap and !verifyheap may incorrectly complain of heap 
consistency errors.
Object <exec cmd="!ListNearObj /d b331dbb0">b331dbb0</exec> has an invalid method table.

在互联网上,我发现了一些帖子,其中提到此问题可能是由版本不匹配引起的,.chain结果似乎可以证实这一点:

0:000> .chain
Extension DLL search Path:
    => Hereby my entire %PATH% environment variable
Extension DLL chain:
    C:\ProgramData\dbg\sym\SOS_x86_x86_4.7.2563.00.dll\5A334E146eb000\SOS_x86_x86_4.7.2563.00.dll: image 4.7.2563.0, API 1.0.0, built Fri Dec 15 05:16:06 2017
        [path: C:\ProgramData\dbg\sym\SOS_x86_x86_4.7.2563.00.dll\5A334E146eb000\SOS_x86_x86_4.7.2563.00.dll]
    sos: image 4.6.1087.0, API 1.0.0, built Wed Nov 30 05:49:55 2016
        [path: C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\sos.dll]

如您所见,确实确实存在版本不匹配:

C:\...\SOS (ALL CAPS) seems to be of version 4.7.2653
sos (small letters)   seems to be of version 4.6.1087

让我们解决这个问题:

0:000> .unload C:\ProgramData\dbg\sym\SOS_x86_x86_4.7.2563.00.dll\5A334E146eb000\SOS_x86_x86_4.7.2563.00.dll
0:000> .load C:\ProgramData\dbg\sym\SOS_x86_x86_4.6.1087.00.dll\583E5B8E6b1000\SOS_x86_x86_4.6.1087.00.dll
// I found this file, somewhere on my PC, I just hope it's correct :-)

这可以解决问题吗?似乎不是:

0:000> !DumpHeap -stat
The garbage collector data structures are not in a valid state for traversal.
It is either in the "plan phase," where objects are being moved around, or
we are at the initialization or shutdown of the gc heap. Commands related to 
displaying, finding or traversing objects as well as gc heap segments may not 
work properly. !dumpheap and !verifyheap may incorrectly complain of heap 
consistency errors.
Object <exec cmd="!ListNearObj /d b331dbb0">b331dbb0</exec> has an invalid method table.

好的。因此仍然没有解决方案。可能还有其他版本错误吗?

0:000> .cordll
CLR DLL status: Loaded DLL C:\ProgramData\dbg\sym\mscordacwks_x86_x86_4.7.2563.00.dll\5A334E146eb000\mscordacwks_x86_x86_4.7.2563.00.dll

的确,CLR似乎也在指该错误的版本。让我们解决一个问题:

0:000> .cordll -u
CLR DLL status: No load attempts

(首先卸载当前的,然后加载新的)

0:000> .cordll -lp C:\ProgramData\dbg\sym\mscordacwks_x86_x86_4.6.1087.00.dll\583E5B8E6b1000\mscordacwks_x86_x86_4.6.1087.00.dll
// Again a file I found somewhere on my PC, but it seems not to be working:
CLRDLL: Consider using ".cordll -lp <path>" command to specify .NET runtime directory.
CLR DLL status: ERROR: Unable to load DLL C:\ProgramData\dbg\sym\mscordacwks_x86_x86_4.6.1087.00.dll\583E5B8E6b1000\mscordacwks_x86_x86_4.6.1087.00.dll\mscordacwks_x86_x86_4.7.2563.00.dll, Win32 error 0n87

现在我没有选择了:在谷歌搜索Win32 error 0n87时,我发现有关错误参数的信息,转储调查有误,但没有办法加载此CLR DLL。

有人可以在这里帮助我吗(也许我们可以先确定我需要选择哪个版本,我只是随机选择了一个:-))?
预先感谢

1 个答案:

答案 0 :(得分:0)

  

0:000> .load sos

该命令将从WinDbg插件目录加载SOS扩展。通常,这是.NET 1.x的版本,当时该版本并未随.NET Framework安装一起提供。

.NET框架的较新版本随附有合适版本的SOS DLL。它安装在.NET Framework目录中,而不是WinDbg目录中。

稍后,我们看到上述命令已加载版本4.6.1087.0。除了文件是手动交换的以外,我真的无法解释。

  

垃圾收集器的数据结构处于无效的遍历状态。

如果Internet认为此可能是版本不匹配,那可能是正确的-我无法判断。

另一种选择是,该语句完全为真,并且当前正在进行垃圾回收,因此堆不一致。

第三个选项与本机代码(C ++或类似代码)有关,本机代码已写入.NET内存并破坏了一些堆信息。

  

[...]似乎由.chain结果确认:

因此,我们看到已加载2个版本的SOS。显然其中一个已经被加载(例如,!analyze,您之前运行过吗?),另一个已经被.load sos命令加载了。

  

让我们解决这个问题:[...]

您正在尝试使用.unload.load解决问题。但是,这只会卸载一个SOS DLL,然后再次加载第二个。如果您想要一个简单的SOS版本,则应该.unload进行2次(所有SOS DLL)访问,然后加载正确的版本。

  

这可以解决问题吗?似乎不是

如前所述,GC可能正在运行。您可能对以下相关问题感兴趣:How to capture a process memory dump of a .NET process when .NET is not in the middle of a garbage collection (GC)

通过查看本机调用堆栈(~*k),应该可以弄清楚.NET当前是否在进行垃圾收集。

  

是不是还有其他错误版本?

     

实际上,CLR似乎也指的是错误的版本。

好吧,您从未确定(或至少没有告诉我们)加载到进程中的.NET版本。进行lm vm clr可以为您提供已加载的版本(长期运行的进程例外,并且同时安装了更新,因此版本信息可能是错误的,因为它是在捕获崩溃时从磁盘读取的)转储)。

加载适当的SOS的常用命令是.loadby sos clr,它告诉WinDbg从clr.dll所在的完全相同的位置加载SOS。如果故障转储来自您的计算机,则此方法有效。如果您从其他人那里获取故障转储,则可能会更加复杂。

  

.cordll -lp C:\ProgramData\dbg\sym\mscordacwks_x86_x86_4.6.1087.00.dll\583E5B8E6b1000\mscordacwks_x86_x86_4.6.1087.00.dll

-lp代表从路径加载,但您指定了文件名。如果您看到错误消息,它会说两次mscordacwks_x86_x86_4.6.1087.00.dll

但是,我怀疑纠正mscordacwks是否会有所帮助-它从未抱怨过错。错误消息如下所示:

CLRDLL: [...]\mscordacwks.dll:<loaded version> doesn't match desired version <expected version>

摘要

  1. 如果只需要一个版本的SOS,请卸载所有个其他版本
  2. 如果堆处于无效状态,则可能恰好是该堆,而不是版本不匹配。另一种选择是通过在.NET堆中编写一些本机代码来破坏堆。
  3. 捕获未进行垃圾收集的故障转储
  4. 向我们提供有关CLR版本,本机调用堆栈等的更多信息,以便我们更好地帮助您(在发布新问题之前进行一些研究)