为什么没有堆栈跟踪使用 WinDbg !heap -a -p 和 .Net NT 服务?

Why no stack trace using WinDbg !heap -a -p with .Net NT service?

我有一个用 .Net 4.5 编写的 Windows NT 服务,存在非托管内存泄漏。

我相信我已经找到泄漏的分配,但我没有得到任何堆栈跟踪。这是我所看到的: 0:022> !heap -s

******************************************************************
                                          NT HEAP STATS BELOW
******************************************************************
LFH Key                   : 0x057e4cff15073499
Termination on corruption : ENABLED
      Heap     Flags   Reserv  Commit  Virt   Free  List   UCR
                        (k)     (k)    (k)     (k) length
------------------------------------------------------------------
000000d80a200000 00000002    8376   7964   8176    564   236     4
000000d80a070000 00008000      64      4     64      2     1     1
000000d80a470000 00001002     260     64     60      8     7     1
000000d80a420000 00001002    1280    104   1080     15    10     2
000000d80a870000 00001002      60      8     60      2     1     1
000000d80a940000 00041002      60      8     60      5     1     1
000000d823320000 00041002      60     16     60      5     1     1
000000d8238f0000 00001002    7416   3160   7216     52    54     4
000000d8241f0000 00001002     260     64     60      7     5     1
000000d825110000 00001002      60      8     60      5     1     1
000000d825280000 00001002      60     12     60      3     2     1
000000d824e60000 00001002      60      8     60      5     1     1
000000d825840000 00001002     260     44     60      9     7     1
------------------------------------------------------------------

接下来,000000d8238f0000 堆看起来很可疑:

0:022> !heap -stat -h 000000d8238f0000
heap @ 000000d8238f0000
group-by: TOTSIZE max-display: 20
size     #blocks     total     ( %) (percent of total busy bytes)
370 60f - 14d390  (58.11)
50 59e - 1c160  (4.90)
21a 46 - 931c  (1.60)
87c5 1 - 87c5  (1.48)
200 32 - 6400  (1.09)
298 26 - 6290  (1.07)
219 2c - 5c4c  (1.01)
278 22 - 53f0  (0.91)
1b7 30 - 5250  (0.90)
1e3 29 - 4d5b  (0.84)
1cd 28 - 4808  (0.79)
279 1b - 42c3  (0.73)
26a 1b - 412e  (0.71)
25b 1b - 3f99  (0.69)
1e9 21 - 3f09  (0.69)
344 13 - 3e0c  (0.68)
2e2 14 - 39a8  (0.63)
2b6 15 - 38ee  (0.62)
216 1b - 3852  (0.61)
213 1b - 3801  (0.61)

接下来大小为 370 的分配:

 0:022> !heap -flt s 370
_HEAP @ d80a200000
          HEAP_ENTRY Size Prev Flags            UserPtr UserSize - state
    000000d8237c96a0 0038 0000  [00]   000000d8237c96b0    00370 - (free)
    000000d8237c9a20 0038 0038  [00]   000000d8237c9a30    00370 - (free)
    000000d8237c9da0 0038 0038  [00]   000000d8237c9db0    00370 - (free)
    000000d8237ca120 0038 0038  [00]   000000d8237ca130    00370 - (free)
_HEAP @ d80a070000
_HEAP @ d80a470000
_HEAP @ d80a420000
_HEAP @ d80a870000
_HEAP @ d80a940000
_HEAP @ d823320000
_HEAP @ d8238f0000
    000000d8238f8a00 0038 0038  [00]   000000d8238f8a10    00370 - (busy)
    000000d8238f8f30 0038 0038  [00]   000000d8238f8f40    00370 - (busy)
    000000d8238fbc00 0038 0038  [00]   000000d8238fbc10    00370 - (busy)

最后是分配的堆栈跟踪:

0:022> !heap -p -a 000000d8237c96b0
address 000000d8237c96b0 found in
_HEAP @ d80a200000
          HEAP_ENTRY Size Prev Flags            UserPtr UserSize - state
    000000d8237c96a0 0038 0000  [00]   000000d8237c96b0    00370 - (free)

有人知道为什么没有堆栈跟踪吗?我尝试了几次分配,none 显示了一个堆栈。完整转储和实时调试的行为相同。

此外,加载和未加载 SOS 的结果相同。

WinDbg 帮助说

-p Specifies that page heap information is being requested

-a [...] Stack traces are included whenever available. [...]

所以你使用了正确的选项。但是,"whenever available"这一点需要考虑。

要获得这些堆栈,请使用 gflags 并启用 "Create user mode stack trace database" 并为其定义一个大小。 50 MB 是可以的,因为它只会记录地址并稍后解析符号名称(因此它不会存储包含所有方法名称的字符串)。

SOS 适用于 .NET,在发生非托管泄漏时没有帮助。