WinDbg没有告诉我我的字符串在哪里扎根

时间:2010-07-08 10:48:39

标签: .net string memory-leaks windbg

我正在尝试追踪为什么字符串在我的应用程序中存储了这么久,并且吃掉了过多的内存。我有一个定期运行的Windows服务。

它从数据库中读取数据(以DataSet的形式),然后进行一些处理 - 所有托管的.NET。

Windows服务每5分钟左右触发一次,这会进行一些交叉引用。 DataSet的每一行都不应该花费超过一秒 - 最糟糕的情况!

私人字节的一个阶段> 1.2GB,即使没有可用于处理的数据。没有全局变量,所有处理都在各个方法中完成。

我拍了快照并用WinDbg处理。结果如下:

0:000> !dumpheap -min 85000
 Address       MT     Size
02027f40 00166620   101432 Free
28411000 79330b24 536870936     
48c11000 79333594 226273040     
08411000 79330b24 452546504     
total 4 objects
Statistics:
      MT    Count    TotalSize Class Name
00166620        1       101432      Free
79333594        1    226273040 System.Byte[]
79330b24        2    989417440 System.String
Total 4 objects

因此我们希望找到导致问题的2个字符串:

0:000> !dumpheap -mt 79330b24  -min 85000
 Address       MT     Size
28411000 79330b24 536870936     
08411000 79330b24 452546504     
total 2 objects
Statistics:
      MT    Count    TotalSize Class Name
79330b24        2    989417440 System.String
Total 2 objects

现在我想找出这两个位置的位置,但是当我使用!gcroot时,它不会返回任何结果:

0:000> !gcroot 28411000 
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 0 OSTHread 2970
Scan Thread 2 OSTHread 2ab4
Scan Thread 3 OSTHread 12ac
Scan Thread 4 OSTHread 1394
Scan Thread 5 OSTHread 1b78
Scan Thread 8 OSTHread 1364
Scan Thread 9 OSTHread 226c
Scan Thread 10 OSTHread 1694
0:000> !gcroot 08411000 
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 0 OSTHread 2970
Scan Thread 2 OSTHread 2ab4
Scan Thread 3 OSTHread 12ac
Scan Thread 4 OSTHread 1394
Scan Thread 5 OSTHread 1b78
Scan Thread 8 OSTHread 1364
Scan Thread 9 OSTHread 226c
Scan Thread 10 OSTHread 1694

我不明白我做错了什么,或者为什么无法找到字符串的根。我已经完成了!做它,它只是说字符串是不可打印的:

0:000> !do 28411000 
Name: System.String
MethodTable: 79330b24
EEClass: 790ed65c
Size: 536870930(0x20000012) bytes
 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: <String is invalid or too large to print>

Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
79332d70  4000096        4         System.Int32  0 instance 268435457 m_arrayLength
79332d70  4000097        8         System.Int32  0 instance 226273026 m_stringLength
79331804  4000098        c          System.Char  0 instance       57 m_firstChar
79330b24  4000099       10        System.String  0   shared   static Empty
    >> Domain:Value  00159f38:01021198 <<
79331754  400009a       14        System.Char[]  0   shared   static WhitespaceChars
    >> Domain:Value  00159f38:010217d4 <<

0:000> !do 08411000 
Name: System.String
MethodTable: 79330b24
EEClass: 790ed65c
Size: 452546502(0x1af94fc6) bytes
 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: <String is invalid or too large to print>

Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
79332d70  4000096        4         System.Int32  0 instance 226273243 m_arrayLength
79332d70  4000097        8         System.Int32  0 instance 226273242 m_stringLength
79331804  4000098        c          System.Char  0 instance       45 m_firstChar
79330b24  4000099       10        System.String  0   shared   static Empty
    >> Domain:Value  00159f38:01021198 <<
79331754  400009a       14        System.Char[]  0   shared   static WhitespaceChars
    >> Domain:Value  00159f38:010217d4 <<

有人可以帮忙吗?

-

更新

!eeheap -gc

Number of GC Heaps: 1
generation 0 starts at 0x01175764
generation 1 starts at 0x011756dc
generation 2 starts at 0x01021000
ephemeral segment allocation context: none
 segment    begin allocated     size
01020000 01021000  0117b770 0x0015a770(1419120)
Large object heap starts at 0x02021000
 segment    begin allocated     size
02020000 02021000  02040d88 0x0001fd88(130440)
28410000 28411000  48411018 0x20000018(536870936)
48c10000 48c11000  563db710 0x0d7ca710(226273040)
08410000 08411000  233a5fc8 0x1af94fc8(452546504)
Total Size  0x488d9be8(1217240040)
------------------------------
GC Heap Size  0x488d9be8(1217240040)

更新2:我删除了对XML的引用,因为这个特定程序不处理XML - 我的不好。


更新3:

以下是使用psscor2.dll的结果

0:000> !heapstat -inclUnrooted
Heap     Gen0         Gen1         Gen2         LOH
Heap0    32780        68316        1324728      1217845888  

Free space:                                                 Percentage
Heap0    12           67212        59764        101640      SOH:  8% LOH:  0%

Unrooted objects:                                           Percentage
Heap0    2684         1104         757416       1217715448  SOH: 53% LOH: 99%

2 个答案:

答案 0 :(得分:7)

EDITED (D'哦,需要更多咖啡)这些字符串大于85,000字节,因此它们将驻留在大型对象堆上,这很少被垃圾收集而不会被压缩(导致碎片,特别是如果你要分配大量短期大型物体)。

WinDbg告诉你的是正确的 - 这些没有root并且它们是垃圾,但是由于它们在LOH上,它们可能不会很快被清除(如果有的话)。

您肯定需要重新考虑如何处理XML,查看流入/流出数据,而不是预先在内存中加载/创建。

答案 1 :(得分:1)

只有在有内存压力时才会收集LOH中的对象。只有在进行完整收集时,GC才会收集LOH中的对象。

psscor2.dll(调试托管代码的扩展名)有一个命令

!HeapStat [-inclUnrooted | -iu]
!eeheap

相比,

只会转储有效的根