使用SOS.dll调查内存泄露

来源:互联网 发布:神之浩劫等待游戏数据 编辑:程序博客网 时间:2024/06/04 22:52
1.用windbg或者VS加载SOS.dll, 可以参考我的另外一篇“如何用Visual Studio集成SOS.dll进行调试
2. 
(1)用GCHandleLeaks调查
     具体示例如下:

0:003> !gchandleleaks

-------------------------------------------------------------------------------

GCHandleLeaks will report any GCHandles that couldn't be found in memory.     

Strong and Pinned GCHandles are reported at this time. You can safely abort the

memory scan with Control-C or Control-Break.                                  

-------------------------------------------------------------------------------

Found 249 handles:

0000000001dc1200     0000000001dc1208     0000000001dc1210    0000000001dc1218    

0000000001dc1220     0000000001dc1228     0000000001dc1230    0000000001dc1238    

0000000001dc1240     0000000001dc1248     0000000001dc1250    0000000001dc1258    

0000000001dc1260     0000000001dc1268     0000000001dc1270    0000000001dc1278    

0000000001dc1280     0000000001dc1288     0000000001dc1290    0000000001dc1298    

0000000001dc12a0     0000000001dc12a8     0000000001dc12b0    0000000001dc12b8    

(the list goes on)

Searching memory

Found 0000000001dc1ff8 at location 000000000012ce48

Found 0000000001dc1380 at location 0000000000145870

Found 0000000001dc1390 at location 0000000000145918

Found 0000000001dc1378 at location 00000000001557f8

------------------------------------------------------------------------------

Some handles were not found. If the number of not-found handles grows over the

lifetime of your application, you may have a GCHandle leak. This will cause  

the GC Heap to grow larger as objects are being kept alive, referenced only  

by the orphaned handle. If the number doesn't grow over time, note that there

may be some noise in this output, as an unmanaged application may be storing 

the handle in a non-standard way, perhaps with some bits flipped. The memory 

scan wouldn't be able to find those.                                         

------------------------------------------------------------------------------

Didn't find 232 handles:

0000000001dc1200     0000000001dc1208     0000000001dc1210    0000000001dc1218    

0000000001dc1220     0000000001dc1228     0000000001dc1230    0000000001dc1238    

0000000001dc1240     0000000001dc1248     0000000001dc1250    0000000001dc1258    

0000000001dc1260     0000000001dc1268     0000000001dc1270    0000000001dc1278    

0000000001dc1280     0000000001dc1288     0000000001dc1290    0000000001dc1298    

...


"Didn't find XXX handles"就是我们需要关注的有可能泄露的句柄, 我们选一个进行查看, 如下:

0:003> !dumpobj poi(0000000001dc1280)

Name: BloatedObject

MethodTable: 00000642801315c0

EEClass: 0000064280163cd0

Size: 32(0x20) bytes

 (C:\pub\eetwc\windowh.exe)

Fields:

              MT    Field   Offset                 Type VT    Attr            Value Name

000006423756d248  4000001        8 System.IO.TextWriter  0 instance 0000000010353c28 tw

00000642375dba38  4000002       10        System.Byte[]  0 instance 0000000022e50080 ba



(2)利用dumpheap -stat和dumpobj
首先用dumpheap -stat列出所有类型的堆信息, 如下:

0:000> !dumpheap -stat
0x79c489a0          1            12 System.Runtime.Remoting.Messaging.ClientContextTerminatorSink
0x79bf9aec          1            12 System.IO.TextReader/NullTextReader
0x79be7078          1            12 System.Runtime.Remoting.Proxies.ProxyAttribute
0x79bce8e0          1            12 System.Runtime.InteropServices.ComVisibleAttribute
0x79bce7c8          1            12 System.CLSCompliantAttribute
0x79bc08e0          1            12 System.Empty
0x0618ae68          1            12 System.Web.Configuration.CustomErrorsConfigHandler
0x061887f8          1            12 System.Web.UI.WebControls.UnitConverter
0x06180848          1            12 System.Drawing.ColorConverter
0x05dbfbc4          1            12 System.Data.Res

第一列是地址,第二列是数量, 第三列是总共大小,第四列是具体类型名字, 需要注意的是第三列总共大小不包含成员变量的大小。
在其中找到异常的类型的堆地址, 比如有些类型的数量太大。 而后利用dumpobj来查看, 如下:

0:000> !dumpobj 0x05dbfbc4
Name: System.Data.DataSet
MethodTable 0x060bbd2c
EEClass 0x060d2614
Size 80(0x50) bytes
GC Generation: 2
mdToken: 0x0200003b  (c:\windows\assembly\gac\system.data\1.0.5000.0__b77a5c561934e089\system.data.dll)
FieldDesc*: 0x060bb358
        MT      Field     Offset                 Type       Attr      Value Name
0x060b252c 0x4000583      0x4                CLASS   instance 0x00000000 site
0x060b252c 0x4000584      0x8                CLASS   instance 0x00000000 events
0x060b252c 0x4000582        0                CLASS     shared   static EventDisposed
    >> Domain:Value 0x001192a0:NotInit  0x0017fc40:NotInit  0x044b7b28:0x1c357cb8 <<
0x060bbd2c 0x40003d3      0xc                CLASS   instance 0x00000000 defaultViewManager
0x060bbd2c 0x40003d4     0x10                CLASS   instance 0x3920ee28 tableCollection
0x060bbd2c 0x40003d5     0x14                CLASS   instance 0x3920ed9c relationCollection
0x060bbd2c 0x40003d6     0x18                CLASS   instance 0x00000000 extendedProperties
0x060bbd2c 0x40003d7     0x1c                CLASS   instance 0x1c357c90 dataSetName
0x060bbd2c 0x40003d8     0x20                CLASS   instance 0x182d0224 _datasetPrefix
0x060bbd2c 0x40003d9     0x24                CLASS   instance 0x182d0224 namespaceURI
0x060bbd2c 0x40003da     0x40       System.Boolean   instance 0 caseSensitive
0x060bbd2c 0x40003db     0x28                CLASS   instance 0x14309a0c culture
0x060bbd2c 0x40003dc     0x41       System.Boolean   instance 1 enforceConstraints
0x060bbd2c 0x40003dd     0x42       System.Boolean   instance 0 fInReadXml
0x060bbd2c 0x40003de     0x43       System.Boolean   instance 0 fInLoadDiffgram
0x060bbd2c 0x40003df     0x44       System.Boolean   instance 0 fTopLevelTable
0x060bbd2c 0x40003e0     0x45       System.Boolean   instance 0 fInitInProgress
0x060bbd2c 0x40003e1     0x46       System.Boolean   instance 1 fEnableCascading
0x060bbd2c 0x40003e2     0x47       System.Boolean   instance 0 fIsSchemaLoading
0x060bbd2c 0x40003e3     0x2c                CLASS   instance 0x00000000 rowDiffId
0x060bbd2c 0x40003e4     0x48       System.Boolean   instance 0 fBoundToDocument
0x060bbd2c 0x40003e5     0x30                CLASS   instance 0x00000000 onPropertyChangingDelegate
0x060bbd2c 0x40003e6     0x34                CLASS   instance 0x00000000 onMergeFailed
0x060bbd2c 0x40003e7     0x38                CLASS   instance 0x00000000 onDataRowCreated
0x060bbd2c 0x40003e8     0x3c                CLASS   instance 0x00000000 onClearFunctionCalled
0x060bbd2c 0x40003e9        0                CLASS     shared   static zeroTables
    >> Domain:Value 0x0017fc40:NotInit  0x044b7b28:0x1c357c80 <<

如果想要查看对象的实际大小值,即也包含成员变量的大小。 请用!objsize 内存地址
我们也可以指定查看具体类型的堆地址, 请用!dumpheap -type 类型名


(3)使用clrstack和finalizeQueue
我们用clrstack查看当前gc中对象情况, 然后用finalizeQueue查看即将要被回收的对象情况, 两者对比下,数量不对或者没被回收的都有可能是内存泄露。



最后, 调查内存泄露是个费时费力还不一定有结果的事情, 祝愿大家都能找出具体问题。


0 0
原创粉丝点击