查看w3wp进程占用的内存及.NET内存泄露,死锁分析

📅 2026/7/4 9:05:44
查看w3wp进程占用的内存及.NET内存泄露,死锁分析
基础知识在分析之前先上一张图从上面可以看到这个w3wp进程占用了376M内存启动了54个线程。在使用windbg查看之前看到的进程含有*32字样意思是在64位机器上已32位方式运行w3wp进程。这个可以通过查看IIS Application Pool 的高级选项进行设置好了接下打开Windbg看看这个w3wp进程占用了376M内存启动的54个线程。1. 加载 WinDbg SOS 扩展命令.load C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll2. !dumpheap -stat!DumpHeap 将遍历 GC 堆对对象进行分析。MT Count TotalSize Class Name78eb9834 1 12 System.ServiceModel.ServiceHostingEnvironmentHostingManagerExtensionHelper0118c800 101 14824 Free...63ce0004 19841 1111096 System.Reflection.RuntimeMethodInfo63ce2ee4 11080 2061036 System.Int32[]63ce0d48 34628 2242596 System.String63ce37b8 20012 3264884 System.Byte[]63cb4518 157645 4940676 System.Object[]Total 524310 objects可以看到w3wp上总共有524310个对象 共占用了这些内存。我们可以将上述上述列出的这些对象归为2类1. 有根对象在应用程序中对这些对象存在引用2. 自从上次垃圾回收之后新创建或无跟对象要注意的是Free这项0118c800 101 14824 Free这项一般都是GC not yet Compacted的空间或一些堆上分配的禁止GC compacted钉扣对象.第一栏 : 类型的方法列表 MT(method type for the type)第二栏堆上的对象数量第三栏所有同类对象的总大小3. !dumpheap -mt 63ce0d48查看 63ce0d48 单元的有哪些对象。4. !do 103b3360看看103b3360地址的string包含哪些内容可见103b3360地址的字符串valueSystem.Web.UI.PageRequestManager:AsyncPostBackError, 占120bytes. 这个字符串对象包含3个字段它们的偏移量分别是4812。5. dd 103b3360看看103b3360的值从左往右第一列是地址而第二列开始则是地址上的数据。6. !dumpheap -type String -min 100看看堆上所有大于100字节的字符串。 注意假如 -min 85000(大于85000字节的字符串或对象将存储在大对象堆上).二. NET内存泄露分析案例1 基础认识.net世界里GC是负责垃圾回收的但GC仅仅是回收哪些不可及的对象无根对象对于有应用的有根对象GC对此无能为力。.net一些内存泄漏的根本原因使用静态引用未退订的事件作者认为这是最常见的内存泄漏原因未退订的静态事件未调用Dispose方法使用不彻底的Dispose方法在Windows Forms中对BindingSource的误用未在WorkItem/CAB上调用Remove一些避免内存泄漏的建议对象的创建者或拥有者负责销毁对象而不是使用者当不再需要一个事件订阅者时退订此事件为确保安全可以在Dispose方法中退订当对象不再触发事件时应该将对象设为null来移除所有的事件订阅者当模型和视图引用同一个对象时推荐给视图传递一个此对象的克隆以防止无法追踪谁在使用哪个对象对系统资源的访问应该包装在using块中这将在代码执行后强制执行Dispose对这些做基本了解后我们将步入正题。2. 案例分析先上测试代码View Code需要说明的是这里程序里面定义了一个Static 字符串及使用了Ionic.Zip 这个Zip压缩包仅仅是为了模拟内存堆积现象没有调用zip.Dispose()方法事实上Ionic.Zip并不会造成内存泄露。正式开始了啊哈好极了。 运行程序好家伙果然很耗费内存 这么个小程序吃了287M,并启动了12个线程.0:005 .load C:\Windows\Microsoft.NET\Framework64\v2.0.50727\sos.dll0:005 .load C:\Symbols\sosex_64\sosex.dll0:005 !dumpheap -stat1 0:012 !dumpheap -stat 2 PDB symbol for mscorwks.dll not loaded 3 total 12840 objects 4 Statistics: 5 MT Count TotalSize Class Name 6 000007ff001d2248 1 24 System.Collections.Generic.Dictionary2ValueCollection[[System.String, mscorlib],[Ionic.Zip.ZipEntry, Ionic.Zip.Reduced]] 7 000007ff000534f0 1 24 ZipTest.LeakTest 8 000007fee951e8e8 1 24 System.IO.TextReaderNullTextReader 9 000007fee94f8198 1 24 System.Security.Cryptography.RNGCryptoServiceProvider 11 ... 43 000007ff001d9130 1041 66624 Ionic.Zlib.DeflateManagerCompressFunc 44 000007fee94d2d40 1023 73656 System.Threading.ExecutionContext 45 000007fee951e038 3075 1387592 System.UInt32[] 46 000007fee951ca10 3179 2450704 System.Int16[] 47 0000000000207800 261 67034512 Free 48 000007fee94d7d90 514 134251544 System.String 49 000007fee94dfdd0 102 138593344 System.Byte[] 50 Total 12840 objects果然我们看到了里面有2类大对象分别占用了134M和138M . 好家伙0:005 !dumpheap -mt1 0:012 !dumpheap -mt 000007fee94dfdd0 2 Address MT Size 3... 24 00000000026f11f0 000007fee94dfdd0 65560 25 0000000002701288 000007fee94dfdd0 65560 26 00000000027112a0 000007fee94dfdd0 65592 27 0000000002722b50 000007fee94dfdd0 65560 28 0000000002752b98 000007fee94dfdd0 65560 29 ... 47 000000000290ab98 000007fee94dfdd0 65560 48 000000000293abe0 000007fee94dfdd0 65560 49 ... 64 0000000002ac1378 000007fee94dfdd0 65560 65 0000000002ad1410 000007fee94dfdd0 65560 66... 103 00000000165a71e0 000007fee94dfdd0 67108888 104 0000000027c11000 000007fee94dfdd0 67108888 105 total 102 objects 106 Statistics: 107 MT Count TotalSize Class Name 108 000007fee94dfdd0 102 138593344 System.Byte[] 109 Total 102 objects果然有那么多65592和65560啊 啊随便找一个看一下0:005 !do 0000000002ba47901 0:012 !do 0000000002ba4790 2 Name: System.Byte[] 3 MethodTable: 000007fee94dfdd0 4 EEClass: 000007fee90e26b0 5 Size: 65590(0x10036) bytes 6 Array: Rank 1, Number of elements 65566, Type Byte 7 Element Type: System.Byte 8 Fields: 9 None哦。这是个一维的数组有65566字节推测应该好像是shortint16长度。继续!gcroot 0000000002b42dd00:012 !gcroot 0000000002b42dd0 Note: Roots found on stacks may be false positives. Run !help gcroot for more info. Scan Thread 0 OSTHread 1d3c RSP:18ef58:Root:00000000025c5b88(Ionic.Zip.ZipFile)- 00000000025d2578(Ionic.Zlib.ParallelDeflateOutputStream)- 00000000025dc528(System.Collections.Generic.List1[[Ionic.Zlib.WorkItem, Ionic.Zip.Reduced]])- 000000000294ac38(System.Object[])- 0000000002b32d78(Ionic.Zlib.WorkItem)- 0000000002b42dd0(System.Byte[]) ... Scan Thread 10 OSTHread 3718这里有点看头了看其跟对象 Ionic.Zip.ZipFile 这个对象占着没销毁的内存呢RSP:18ef58:Root:00000000025c5b88(Ionic.Zip.ZipFile)-00000000025d2578(Ionic.Zlib.ParallelDeflateOutputStream)-00000000025dc528(System.Collections.Generic.List1[[Ionic.Zlib.WorkItem, Ionic.Zip.Reduced]])-000000000294ac38(System.Object[])-0000000002b32d78(Ionic.Zlib.WorkItem)-0000000002b42dd0(System.Byte[])换一个看看0:012 !gcroot 00000000029bc730 Note: Roots found on stacks may be false positives. Run !help gcroot for more info. Scan Thread 0 OSTHread 1d3c RSP:18ef58:Root:00000000025c5b88(Ionic.Zip.ZipFile)- 00000000025d2578(Ionic.Zlib.ParallelDeflateOutputStream)- 00000000025dc528(System.Collections.Generic.List1[[Ionic.Zlib.WorkItem, Ionic.Zip.Reduced]])- 000000000294ac38(System.Object[])- 00000000029ac6d8(Ionic.Zlib.WorkItem)- 00000000029bc730(System.Byte[]) ... Scan Thread 10 OSTHread 3718查看下其代龄0:012 !gcgen 00000000029bc730GEN 1看到了这个byte[]在1代。到此为止还记得有个静态字符串吧private static string leakString;我们回头再去看看!dumpheap -type String -min 10000:012 !dumpheap -type String -min 1000 Address MT Size 00000000025c26e0 000007fee94d7d90 8032 00000000025cca30 000007fee94d7d90 1176 00000000025cd308 000007fee94d7d90 1600 000000001ae81000 000007fee94d7d90 134215704 total 4 objects Statistics: MT Count TotalSize Class Name 000007fee94d7d90 4 134226512 System.String Total 4 objectsNext,0:012 !do 00000000025c26e00:012 !do 00000000025c26e0 Name: System.String MethodTable: 000007fee94d7d90 EEClass: 000007fee90de560 Size: 8026(0x1f5a) bytes (C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll) String: LEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKL.... EAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAK Fields: MT Field Offset Type VT Attr Value Name 000007fee94df000 4000096 8 System.Int32 1 instance 4001 m_arrayLength 000007fee94df000 4000097 c System.Int32 1 instance 4000 m_stringLength 000007fee94d97d8 4000098 10 System.Char 1 instance 4c m_firstChar 000007fee94d7d90 4000099 20 System.String 0 shared static Empty Domain:Value 000000000062b1d0:00000000025c1308 000007fee94d9688 400009a 28 System.Char[] 0 shared static WhitespaceChars Domain:Value 000000000062b1d0:00000000025c1a90 再看下这个对象!dumpobj 00000000025c26e00:012 !dumpobj 00000000025c26e0 Name: System.String MethodTable: 000007fee94d7d90 EEClass: 000007fee90de560 Size: 8026(0x1f5a) bytes (C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)(C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll) String: LEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKL.... EAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAK Fields:MT Field Offset Type VT Attr Value Name 000007fee94df000 4000096 8 System.Int32 1 instance 4001 m_arrayLength 000007fee94df000 4000097 c System.Int32 1 instance 4000 m_stringLength 000007fee94d97d8 4000098 10 System.Char 1 instance 4c m_firstChar 000007fee94d7d90 4000099 20 System.String 0 shared static Empty Domain:Value 000000000062b1d0:00000000025c1308 000007fee94d9688 400009a 28 System.Char[] 0 shared static WhitespaceChars Domain:Value 000000000062b1d0:00000000025c1a90 显示结果一样StringLEAKLEAKLEAKLEAKLEAK......,字符串长度4000和我们的测试代码吻合1 public LeakTest() 2 { 3 for (int i 0; i 1000; i) 4 { 5 leakString LEAK; 6 } 7 }