如何分析windbg中的<unclassified>内存使用情况

Mar*_*ark 22 memory debugging unmanaged windbg

这是在x64计算机上运行的.NET v4 Windows服务应用程序.在经过几天稳定运行后的某些时候,Windows服务内存消耗会像疯了一样飙升直到它崩溃.我能够以1.2 GB捕获它并捕获内存转储.这就是我得到的

如果我在我的转储文件上的windbg中运行!address -summary,我得到以下结果

!地址 - 简介

--- Usage Summary ------ RgnCount ------- Total Size -------- %ofBusy  %ofTotal
Free                     821      7ff`7e834000 (   7.998 Tb)           99.98%
<unclassified>           3696       0`6eece000 (   1.733 Gb)  85.67%   0.02%
Image                    1851       0`0ea6f000 ( 234.434 Mb)  11.32%   0.00%
Stack                    1881       0`03968000 (  57.406 Mb)  2.77%    0.00%
TEB                      628        0`004e8000 (   4.906 Mb)  0.24%    0.00%
NlsTables                1          0`00023000 ( 140.000 kb)  0.01%    0.00%
ActivationContextData    3          0`00006000 (  24.000 kb)  0.00%    0.00%
CsrSharedMemory          1          0`00005000 (  20.000 kb)  0.00%    0.00%
PEB                      1          0`00001000 (   4.000 kb)  0.00%    0.00%
-
-
-
--- Type Summary (for busy) -- RgnCount ----- Total Size ----- %ofBusy %ofTotal
MEM_PRIVATE                        5837 0`7115a000 (  1.767 Gb)  87.34%  0.02%
MEM_IMAGE                          2185 0`0f131000 (241.191 Mb)  11.64%  0.00%
MEM_MAPPED                           40 0`01531000 ( 21.191 Mb)   1.02%  0.00%
-
-
--- State Summary ------------ RgnCount ------ Total Size ---- %ofBusy %ofTotal
MEM_FREE                            821 7ff`7e834000 (  7.998 Tb)        99.98%
MEM_COMMIT                         6127   0`4fd5e000 (  1.247 Gb) 61.66%  0.02%
MEM_RESERVE                        1935   0`31a5e000 (794.367 Mb) 38.34%  0.01%
-
-
--Protect Summary(for commit)- RgnCount ------ Total Size --- %ofBusy %ofTotal
PAGE_READWRITE                     3412 0`3e862000 (1000.383 Mb) 48.29%   0.01%
PAGE_EXECUTE_READ                   220 0`0b12f000 ( 177.184 Mb)  8.55%   0.00%
PAGE_READONLY                       646 0`02fd0000 (  47.813 Mb)  2.31%   0.00%
PAGE_WRITECOPY                      410 0`01781000 (  23.504 Mb)  1.13%   0.00%
PAGE_READWRITE|PAGE_GUARD          1224 0`012f2000 (  18.945 Mb)  0.91%   0.00%
PAGE_EXECUTE_READWRITE              144 0`007b9000 (   7.723 Mb)  0.37%   0.00%
PAGE_EXECUTE_WRITECOPY               70 0`001cd000 (   1.801 Mb)  0.09%   0.00%
PAGE_EXECUTE                          1 0`00004000 (  16.000 kb)  0.00%   0.00%
-
-
--- Largest Region by Usage ----Base Address -------- Region Size ----------
Free                            0`8fff0000        7fe`59050000 (   7.994 Tb)
<unclassified>                  0`80d92000        0`0f25e000 ( 242.367 Mb)
Image                           fe`f6255000       0`0125a000 (  18.352 Mb)
Stack                           0`014d0000        0`000fc000 (1008.000 kb)
TEB                             0`7ffde000        0`00002000 (   8.000 kb)
NlsTables                       7ff`fffb0000      0`00023000 ( 140.000 kb)
ActivationContextData           0`00030000        0`00004000 (  16.000 kb)
CsrSharedMemory                 0`7efe0000        0`00005000 (  20.000 kb)
PEB                             7ff`fffdd000      0`00001000 (   4.000 kb)
Run Code Online (Sandbox Code Playgroud)

首先,为什么未分类显示为1.73 GB,另一次显示为242 MB.(已经回答了.谢谢)

其次,我知道未分类可能意味着托管代码,但是我的堆大小根据!eeheap只有248 MB,实际上匹配242但不接近1.73GB.转储文件大小为1.2 GB,远高于正常情况.我从哪里可以找到使用所有内存的内容.托管堆世界中的任何东西都不到248 MB,但我使用的是1.2 GB.

谢谢

编辑

如果我这样做!heap -si得到以下内容

LFH Key                   : 0x000000171fab7f20
Termination on corruption : ENABLED
          Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 
                            (k)     (k)    (k)     (k) length      blocks cont. heap 
-------------------------------------------------------------------------------------
Virtual block: 00000000017e0000 - 00000000017e0000 (size 0000000000000000)
Virtual block: 0000000045bd0000 - 0000000045bd0000 (size 0000000000000000)
Virtual block: 000000006fff0000 - 000000006fff0000 (size 0000000000000000)
0000000000060000 00000002  113024 102028 113024  27343  1542    11    3    1c LFH
    External fragmentation  26 % (1542 free blocks)
0000000000010000 00008000      64      4     64      1     1     1    0    0      
0000000000480000 00001002    3136   1380   3136     20     8     3    0    0  LFH
0000000000640000 00041002     512      8    512      3     1     1    0    0      
0000000000800000 00001002    3136   1412   3136     15     7     3    0    0  LFH
00000000009d0000 00001002    3136   1380   3136     19     7     3    0    0  LFH
00000000008a0000 00041002     512     16    512      3     1     1    0    0      
0000000000630000 00001002    7232   3628   7232     18    53     4    0    0  LFH
0000000000da0000 00041002    1536    856   1536      1     1     2    0    0  LFH
0000000000ef0000 00041002    1536    944   1536      4    12     2    0    0  LFH
00000000034b0000 00001002    1536   1452   1536      6    17     2    0    0  LFH
00000000019c0000 00001002    3136   1396   3136     16     6     3    0    0  LFH
0000000003be0000 00001002    1536   1072   1536      5     7     2    0    3  LFH
0000000003dc0000 00011002     512    220    512    100    60     1    0    2      
0000000002520000 00001002     512      8    512      3     2     1    0    0      
0000000003b60000 00001002  339712 168996 339712 151494   976   116    0   18  LFH
    External fragmentation  89 % (976 free blocks)
    Virtual address fragmentation  50 % (116 uncommited ranges)
0000000003f20000 00001002      64      8     64      3     1     1    0      0      
0000000003d90000 00001002      64      8     64      3     1     1    0      0      
0000000003ee0000 00001002      64     16     64     11     1     1    0      0      
-------------------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

Vin*_*nce 16

我最近有一个非常相似的情况,并发现了一些在调查中有用的技术.没有一个是银弹,但每个人都对这个问题有了更多的了解.

1)来自SysInternals的vmmap.exe(http://technet.microsoft.com/en-us/sysinternals/dd535533)可以很好地关联本机​​和托管内存的信息,并在一个漂亮的UI中呈现它.可以使用以下技术收集相同的信息,但这更容易,也是一个不错的起点.遗憾的是,它不适用于转储文件,您需要一个实时进程.

2)"!address -summary"输出是更详细的"!address"输出的汇总.我发现将详细输出放入Excel并运行一些支点很有用.使用这种技术,我发现列为""的大量字节实际上是MEM_IMAGE页面,可能是加载DLL时加载但随后在数据更改时复制的数据页面的副本.我还可以过滤到大区域并钻取特定地址.用牙签和许多祈祷在记忆堆中徘徊是痛苦的,但可以揭示.

3)最后,我在上面做了一个穷人的vmmap.exe技术版本.我加载了转储文件,打开了一个日志,并运行了!地址,!eeheap,!heap和!threads.我还使用!teb定位〜*k中列出的线程环境块.我关闭了日志文件并将其加载到我最喜欢的编辑器中.然后我可以找到一个未分类的块并搜索它是否在一个更详细的命令的输出中弹出.您可以非常快速地将本机和管理堆相关联,以便从您可疑的未分类区域中清除那些.

这些都是手动的.我喜欢编写一个脚本,其输出类似于我在上面的技术3中生成的输出,并输出适合查看vmmap.exe的mmp文件.有一天.

最后一点说明:我在vmmap.exe的输出与!地址输出之间进行了关联,并注意到vmmap夫妇从各种来源识别的这些类型的区域(类似于!heap和!eeheap使用),但是!地址不知道关于.也就是说,这些是vmmap.exe标记的东西但是!地址没有:

.data
.pdata
.rdata
.text
64-bit thread stack
Domain 1
Domain 1 High Frequency Heap
Domain 1 JIT Code Heap
Domain 1 Low Frequency Heap
Domain 1 Virtual Call Stub
Domain 1 Virtual Call Stub Lookup Heap
Domain 1 Virtual Call Stub Resolve Heap
GC
Large Object Heap
Native heaps
Thread Environment Blocks
Run Code Online (Sandbox Code Playgroud)

仍有很多"私人"字节下落不明,但同样,如果我可以清除这些,我能够缩小问题范围.

希望这能为您提供有关如何调查的一些想法.我在同一条船上所以我也很欣赏你所发现的东西.谢谢!


Kje*_*nar 2

\xe2\x80\x9c使用摘要\xe2\x80\x9d 告诉您有 3696 个未分类区域,总共 17.33 GB

\n\n

\xe2\x80\x9cLargest Region\xe2\x80\x9d 表明最大的未分类区域为 242 Mb。\n其余未分类(3695 个区域)加在一起使差异达到 17.33 Gb。

\n\n

尝试执行 !heap \xe2\x80\x93s 并总结 Virt col 以查看本机堆的大小,我认为这些也属于非托管存储桶。\n (注意早期版本显示来自 !address 的本机堆显式) -概括)

\n