为什么没有堆栈跟踪使用 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,在发生非托管泄漏时没有帮助。
我有一个用 .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,在发生非托管泄漏时没有帮助。