找回密码
 立即注册
首页 业界区 业界 查看w3wp进程占用的内存及.NET内存泄露,死锁分析 ...

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

俏挺喳 2025-5-29 17:55:39
一 基础知识
0000000000c946d8 OBJ:00000000027736d0在分析之前,先上一张图:

从上面可以看到,这个w3wp进程占用了376M内存,启动了54个线程。
在使用windbg查看之前,看到的进程含有 *32 字样,意思是在64位机器上已32位方式运行w3wp进程。这个可以通过查看IIS Application Pool 的高级选项进行设置:
2.png

好了,接下打开Windbg看看这个w3wp进程占用了376M内存,启动的54个线程。
3.png

1. 加载 WinDbg SOS 扩展命令
.load C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll
2. !dumpheap -stat
!DumpHeap 将遍历 GC 堆对对象进行分析。
0000000000c946d8 OBJ:00000000027736d0 MT0000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 Count0000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 TotalSize0000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 0000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 Class Name
78eb98340000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 10000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 120000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 0000000000c946d8 OBJ:00000000027736d0System.ServiceModel.ServiceHostingEnvironment+HostingManager+ExtensionHelper
0118c8000000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 1010000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 148240000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 Free
...
63ce00040000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 198410000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 1111096 System.Reflection.RuntimeMethodInfo
63ce2ee40000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 110800000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 2061036 System.Int32[]
63ce0d480000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 346280000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 2242596 System.String
63ce37b80000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 200120000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 3264884 System.Byte[]
63cb45180000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 1576450000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 4940676 System.Object[]
Total 524310 objects
可以看到,w3wp上总共有524310个对象, 共占用了这些内存。
我们可以将上述上述列出的这些对象归为2类:
1). 有根对象(在应用程序中对这些对象存在引用)
2). 自从上次垃圾回收之后新创建或无跟对象
要注意的是Free这项:
0118c8000000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 1010000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 148240000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0 Free
这项一般都是GC not yet Compacted的空间或一些堆上分配的禁止GC compacted钉扣对象.
第一栏 : 类型的方法列表 MT(method type for the type)
第二栏:堆上的对象数量
第三栏:所有同类对象的总大小
0000000000c946d8 OBJ:00000000027736d0
3. !dumpheap -mt 63ce0d480000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0
查看 63ce0d480000000000c946d8 OBJ:00000000027736d00000000000c946d8 OBJ:00000000027736d0单元的有哪些对象。
4.png

4. !do 103b3360
看看103b3360地址的string包含哪些内容
5.png

可见,103b3360地址的字符串value="System.Web.UI.PageRequestManager:AsyncPostBackError", 占120bytes. 这个字符串对象包含3个字段,它们的偏移量分别是4,8,12。
5. dd 103b3360
看看103b3360的值
6.png

从左往右第一列是地址,而第二列开始则是地址上的数据。
6. !dumpheap -type String -min 100
看看堆上所有大于100字节的字符串。 注意:假如 -min 85000(大于85000字节的字符串或对象将存储在大对象堆上).0000000000c946d8 OBJ:00000000027736d0
7.png

0000000000c946d8 OBJ:00000000027736d0
二. NET内存泄露分析案例
1 基础认识
0000000000c946d8 OBJ:00000000027736d0 .net世界里,GC是负责垃圾回收的,但GC仅仅是回收哪些不可及的对象(无根对象),对于有应用的有根对象,GC对此无能为力。
0000000000c946d8 OBJ:00000000027736d0 .net一些内存泄漏的根本原因:

  • 使用静态引用
  • 未退订的事件-作者认为这是最常见的内存泄漏原因
  • 未退订的静态事件
  • 未调用Dispose方法
  • 使用不彻底的Dispose方法
  • 在Windows Forms中对BindingSource的误用
  • 未在WorkItem/CAB上调用Remove
一些避免内存泄漏的建议:

  • 对象的创建者或拥有者负责销毁对象,而不是使用者
  • 当不再需要一个事件订阅者时退订此事件,为确保安全可以在Dispose方法中退订
  • 当对象不再触发事件时,应该将对象设为null来移除所有的事件订阅者
  • 当模型和视图引用同一个对象时,推荐给视图传递一个此对象的克隆,以防止无法追踪谁在使用哪个对象
  • 对系统资源的访问应该包装在using块中,这将在代码执行后强制执行Dispose
对这些做基本了解后,我们将步入正题。
2. 案例分析
先上测试代码:0000000000c946d8 OBJ:00000000027736d0
8.gif
9.gif
  1. 1 public class LeakTest
  2. 2     {
  3. 3         private static string leakString;
  4. 4
  5. 5         public LeakTest()
  6. 6         {
  7. 7             for (int i = 0; i < 1000; i++)
  8. 8             {
  9. 9                 leakString += "LEAK";
  10. 10             }
  11. 11         }
  12. 12
  13. 13         public string GetRamdonString()
  14. 14         {
  15. 15             System.Random random = new System.Random();
  16. 16
  17. 17             string str = string.Empty;
  18. 18             for (int i = 0; i < 25; i++)
  19. 19             {
  20. 20                 str += str + random.Next(100);
  21. 21             }
  22. 22             return str;
  23. 23         }
  24. 24
  25. 25         public void NoDispose()
  26. 26         {
  27. 27             string str = GetRamdonString();
  28. 28            
  29. 29             ZipFile zip = new ZipFile();
  30. 30             zip.AddEntry("a.txt", str);
  31. 31             zip.AddEntry("b.txt", str);
  32. 32             zip.Save("test.rar");
  33. 33             //zip.Dispose();
  34. 34         }
  35. 35     }
  36. 36
  37. 37     class Program
  38. 38     {
  39. 39         static void Main(string[] args)
  40. 40         {
  41. 41             LeakTest leakTest = new LeakTest();
  42. 42             leakTest.NoDispose();
  43. 43             Console.ReadLine();
  44. 44         }
  45. 45     }
复制代码
View Code0000000000c946d8 OBJ:00000000027736d0
需要说明的是:
这里程序里面定义了一个Static 字符串,及使用了Ionic.Zip 这个Zip压缩包,仅仅是为了模拟内存堆积现象,没有调用zip.Dispose()方法,事实上Ionic.Zip并不会造成内存泄露。
0000000000c946d8 OBJ:00000000027736d0
正式开始了:
啊哈,好极了。 运行程序,好家伙,果然很耗费内存! 这么个小程序,吃了287M,并启动了12个线程.
10.png

0000000000c946d8 OBJ:00000000027736d0
0000000000c946d8 OBJ:00000000027736d0
0:005> .load C:\Windows\Microsoft.NET\Framework64\v2.0.50727\sos.dll0000000000c946d8 OBJ:00000000027736d0
0:005> .load C:\Symbols\sosex_64\sosex.dll
0:005> !dumpheap -stat
0000000000c946d8 OBJ:00000000027736d0
  1. 1 0:012> !dumpheap -stat
  2. 2 PDB symbol for mscorwks.dll not loaded
  3. 3 total 12840 objects
  4. 4 Statistics:
  5. 5               MT    Count    TotalSize Class Name
  6. 6 000007ff001d2248        1           24 System.Collections.Generic.Dictionary`2+ValueCollection[[System.String, mscorlib],[Ionic.Zip.ZipEntry, Ionic.Zip.Reduced]]
  7. 7 000007ff000534f0        1           24 ZipTest.LeakTest
  8. 8 000007fee951e8e8        1           24 System.IO.TextReader+NullTextReader
  9. 9 000007fee94f8198        1           24 System.Security.Cryptography.RNGCryptoServiceProvider
  10. <br>11 ...<br>43 000007ff001d9130     1041        66624 Ionic.Zlib.DeflateManager+CompressFunc
  11. 44 000007fee94d2d40     1023        73656 System.Threading.ExecutionContext
  12. 45 000007fee951e038     3075      1387592 System.UInt32[]
  13. 46 000007fee951ca10     3179      2450704 System.Int16[]
  14. 47 0000000000207800      261     67034512      Free
  15. 48 000007fee94d7d90      514    134251544 System.String
  16. 49 000007fee94dfdd0      102    138593344 System.Byte[]
  17. 50 Total 12840 objects
复制代码
0000000000c946d8 OBJ:00000000027736d0
0000000000c946d8 OBJ:00000000027736d0
果然,我们看到了里面有2类大对象,分别占用了134M和138M . 好家伙!
0:005> !dumpheap -mt0000000000c946d8 OBJ:00000000027736d0
0000000000c946d8 OBJ:00000000027736d0
  1.   1 0:012> !dumpheap -mt 000007fee94dfdd0      
  2.   2          Address               MT     Size
  3.   3...   
  4. 24 00000000026f11f0 000007fee94dfdd0    65560     
  5. 25 0000000002701288 000007fee94dfdd0    65560     
  6. 26 00000000027112a0 000007fee94dfdd0    65592     
  7. 27 0000000002722b50 000007fee94dfdd0    65560     
  8. 28 0000000002752b98 000007fee94dfdd0    65560     
  9. 29 ...   
  10. 47 000000000290ab98 000007fee94dfdd0    65560     
  11. 48 000000000293abe0 000007fee94dfdd0    65560     
  12. 49 ...     
  13. 64 0000000002ac1378 000007fee94dfdd0    65560     
  14. 65 0000000002ad1410 000007fee94dfdd0    65560     
  15. 66...  
  16. 103 00000000165a71e0 000007fee94dfdd0 67108888     
  17. 104 0000000027c11000 000007fee94dfdd0 67108888     
  18. 105 total 102 objects
  19. 106 Statistics:
  20. 107               MT    Count    TotalSize Class Name
  21. 108 000007fee94dfdd0      102    138593344 System.Byte[]
  22. 109 Total 102 objects
复制代码
果然,有那么多65592和65560啊 啊
随便找一个看一下:
0:005> !do 0000000002ba4790
  1. 1 0:012> !do 0000000002ba4790
  2. 2 Name: System.Byte[]
  3. 3 MethodTable: 000007fee94dfdd0
  4. 4 EEClass: 000007fee90e26b0
  5. 5 Size: 65590(0x10036) bytes
  6. 6 Array: Rank 1, Number of elements 65566, Type Byte
  7. 7 Element Type: System.Byte
  8. 8 Fields:
  9. 9 None
复制代码
0000000000c946d8 OBJ:00000000027736d0
哦。这是个一维的数组,有65566字节,推测应该好像是short(int16)长度。
继续,
!gcroot 0000000002b42dd0
  1. 0:012> !gcroot 0000000002b42dd0
  2. Note: Roots found on stacks may be false positives. Run "!help gcroot" for
  3. more info.
  4. Scan Thread 0 OSTHread 1d3c
  5. RSP:18ef58:Root:00000000025c5b88(Ionic.Zip.ZipFile)->
  6. 00000000025d2578(Ionic.Zlib.ParallelDeflateOutputStream)->
  7. 00000000025dc528(System.Collections.Generic.List`1[[Ionic.Zlib.WorkItem, Ionic.Zip.Reduced]])->
  8. 000000000294ac38(System.Object[])->
  9. 0000000002b32d78(Ionic.Zlib.WorkItem)->
  10. 0000000002b42dd0(System.Byte[])
  11. ...
  12. Scan Thread 10 OSTHread 3718
复制代码
0000000000c946d8 OBJ:00000000027736d0
这里有点看头了! 看其跟对象 Ionic.Zip.ZipFile 这个对象占着没销毁的内存呢!
0000000000c946d8 OBJ:00000000027736d0RSP:18ef58:Root:00000000025c5b88(Ionic.Zip.ZipFile)->
00000000025d2578(Ionic.Zlib.ParallelDeflateOutputStream)->
00000000025dc528(System.Collections.Generic.List`1[[Ionic.Zlib.WorkItem, Ionic.Zip.Reduced]])->
000000000294ac38(System.Object[])->
0000000002b32d78(Ionic.Zlib.WorkItem)->
0000000002b42dd0(System.Byte[])
换一个看看:
  1. 0:012> !gcroot 00000000029bc730
  2. Note: Roots found on stacks may be false positives. Run "!help gcroot" for
  3. more info.
  4. Scan Thread 0 OSTHread 1d3c
  5. RSP:18ef58:Root:00000000025c5b88(Ionic.Zip.ZipFile)->
  6. 00000000025d2578(Ionic.Zlib.ParallelDeflateOutputStream)->
  7. 00000000025dc528(System.Collections.Generic.List`1[[Ionic.Zlib.WorkItem, Ionic.Zip.Reduced]])->
  8. 000000000294ac38(System.Object[])->
  9. 00000000029ac6d8(Ionic.Zlib.WorkItem)->
  10. 00000000029bc730(System.Byte[])
  11. ...
  12. Scan Thread 10 OSTHread 3718
复制代码
0000000000c946d8 OBJ:00000000027736d0
查看下其代龄:
0:012> !gcgen 00000000029bc730
GEN 1
看到了,这个byte[]在1代。
0000000000c946d8 OBJ:00000000027736d0
到此为止,还记得有个静态字符串吧
private static string leakString;
我们回头再去看看,
0000000000c946d8 OBJ:00000000027736d0!dumpheap -type String -min 1000
  1. 0:012> !dumpheap -type String -min 1000
  2.          Address               MT     Size
  3. 00000000025c26e0 000007fee94d7d90     8032     
  4. 00000000025cca30 000007fee94d7d90     1176     
  5. 00000000025cd308 000007fee94d7d90     1600     
  6. 000000001ae81000 000007fee94d7d90 134215704     
  7. total 4 objects
  8. Statistics:
  9.               MT    Count    TotalSize Class Name
  10. 000007fee94d7d90        4    134226512 System.String
  11. Total 4 objects
复制代码
Next,
0:012> !do 00000000025c26e0
  1. 0:012> !do 00000000025c26e0
  2. Name: System.String
  3. MethodTable: 000007fee94d7d90
  4. EEClass: 000007fee90de560
  5. Size: 8026(0x1f5a) bytes
  6. (C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
  7. String: LEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKL....<br>EAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAK
  8. Fields:
  9.               MT    Field   Offset                 Type VT     Attr            Value Name
  10. 000007fee94df000  4000096        8         System.Int32  1 instance             4001 m_arrayLength
  11. 000007fee94df000  4000097        c         System.Int32  1 instance             4000 m_stringLength
  12. 000007fee94d97d8  4000098       10          System.Char  1 instance               4c m_firstChar
  13. 000007fee94d7d90  4000099       20        System.String  0   shared           static Empty
  14.                                  >> Domain:Value  000000000062b1d0:00000000025c1308 <<
  15. 000007fee94d9688  400009a       28        System.Char[]  0   shared           static WhitespaceChars
  16.                                  >> Domain:Value  000000000062b1d0:00000000025c1a90 <<
复制代码
View Code瞧准了,这是个主线程,他在等待Console.ReadLine(). 所以占用了这么长时间。
0000000000c946d8 OBJ:00000000027736d0
再在看一下这13个线程里,哪些是托管堆线程:
!threads
  1. 0:012> !dumpobj 00000000025c26e0
  2. Name: System.String
  3. MethodTable: 000007fee94d7d90
  4. EEClass: 000007fee90de560
  5. Size: 8026(0x1f5a) bytes
  6. (C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
复制代码
在托管堆上启动的线程有10个。这10个线程分别是什么,继续看:
0号MTA: 程序主线程
MTA (Finalizer):这个是Finalizer线程,该线程负责垃圾对象回收。
MTA (Threadpool Worker):这些是ThreadPool创建的线程,这里是Ionic.Zlib.WorkItem产生的工作线程。
另外,CLR根据需要还会开启其他一些线程,如:
并发的GC线程 ,服务器GC线程 ,调试器帮助线程 ,AppDomain卸载线程 等.
0000000000c946d8 OBJ:00000000027736d0
看一下同步块情况,有么有死锁?
!syncblk
!dlk
  1. (C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
  2. String: LEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKL....<br>EAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAK
  3. Fields:
复制代码
显示该程序没有锁相关资源,实际确实没有。
0000000000c946d8 OBJ:00000000027736d0
2 死锁
Lock:lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。 下面的示例包含一个 lock 语句。
lock 关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区。 如果其他线程尝试进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。
0000000000c946d8 OBJ:00000000027736d0
通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。 常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:

  • 如果实例可以被公共访问,将出现 lock (this) 问题。
  • 如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。
  • 由于进程中使用同一字符串的任何其他代码都将共享同一个锁,所以出现 lock("myLock") 问题。
最佳做法是定义 private 对象来锁定, 或 private static 对象变量来保护所有实例所共有的数据。
0000000000c946d8 OBJ:00000000027736d0
3 案例分析
这个案例很简单,上菜:
11.gif
12.gif
  1. 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 <<
复制代码
View Code运行程序,便进入死锁。
ok,上 windbg.
.load C:\Symbols\sosex_64\sosex.dll
0:000> !dlk
0000000000c946d8 OBJ:00000000027736d0<br>
  1. 1  public LeakTest()
  2. 2         {
  3. 3             for (int i = 0; i < 1000; i++)
  4. 4             {
  5. 5                 leakString += "LEAK";
  6. 6             }
  7. 7         }
复制代码
只需敲一个命令,死锁就检测到了。 注意下面这些地址:
  1. 0:012> !runaway
  2. User Mode Time
  3.   Thread       Time
  4.    0:5588      0 days 0:00:05.085
  5.    7:4954      0 days 0:00:01.903
  6.    3:4ddc      0 days 0:00:01.825
  7.    8:5af4      0 days 0:00:01.809
  8.    9:4740      0 days 0:00:01.747
  9.   10:6c38      0 days 0:00:01.731
  10.    4:6a94      0 days 0:00:01.700
  11.    5:43ec      0 days 0:00:01.622
  12.    6:8fdc      0 days 0:00:01.606
  13.   12:1e64      0 days 0:00:00.000
  14.   11:6a4       0 days 0:00:00.000
  15.    2:64b4      0 days 0:00:00.000
  16.    1:69e4      0 days 0:00:00.000
复制代码
  1. 0:012> ~0s
  2. ntdll!ZwRequestWaitReplyPort+0xa:
  3. 00000000`77b714da c3              ret
  4. 0:000> !ClrStack -a
  5. OS Thread Id: 0x5588 (0)
  6. *** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v2.0.50727_64\mscorlib\c3beeeb6432f004b419859ea007087f1\mscorlib.ni.dll
  7. Child-SP         RetAddr          Call Site
  8. 00000000001de670 000007fee9b02c79 DomainNeutralILStubClass.IL_STUB(Microsoft.Win32.SafeHandles.SafeFileHandle, Byte*, Int32, Int32 ByRef, IntPtr)
  9.     PARAMETERS:
  10.         <no data>
  11.         <no data>
  12.         <no data>
  13.         <no data>
  14.         <no data>
  15. 00000000001de790 000007fee9b02d92 System.IO.__ConsoleStream.ReadFileNative(Microsoft.Win32.SafeHandles.SafeFileHandle, Byte[], Int32, Int32, Int32, Int32 ByRef)
  16.     PARAMETERS:
  17.         hFile = <no data>
  18.         bytes = <no data>
  19.         offset = <no data>
  20.         count = <no data>
  21.         mustBeZero = <no data>
  22.         errorCode = 0x00000000001de820
  23.     LOCALS:
  24.         <no data>
  25.         0x00000000001de7c0 = 0x0000000000000000
  26.         <no data>
  27.         <no data>
  28. 00000000001de7f0 000007fee93f08da System.IO.__ConsoleStream.Read(Byte[], Int32, Int32)
  29.     PARAMETERS:
  30.         this = <no data>
  31.         buffer = <no data>
  32.         offset = <no data>
  33.         count = <no data>
  34.     LOCALS:
  35.         0x00000000001de820 = 0x0000000000000000
  36.         <no data>
  37. 00000000001de850 000007fee9412a8a System.IO.StreamReader.ReadBuffer()
  38.     PARAMETERS:
  39.         this = <no data>
  40.     LOCALS:
  41.         <no data>
  42. 00000000001de8a0 000007fee9b0622f System.IO.StreamReader.ReadLine()
  43.     PARAMETERS:
  44.         this = <no data>
  45.     LOCALS:
  46.         <no data>
  47.         <no data>
  48.         <no data>
  49.         <no data>
  50. 00000000001de8f0 000007ff00190188 System.IO.TextReader+SyncTextReader.ReadLine()
  51.     PARAMETERS:
  52.         this = 0x00000000030387b0
  53. 00000000001de950 000007feea23c6a2 ZipTest.Program.Main(System.String[])
  54.     PARAMETERS:
  55.         args = 0x00000000027e2680
  56.     LOCALS:
  57.         0x00000000001de970 = 0x00000000027e26a0
复制代码
  1. 0:012> !threads
  2. ThreadCount: 10
  3. UnstartedThread: 0
  4. BackgroundThread: 9
  5. PendingThread: 0
  6. DeadThread: 0
  7. Hosted Runtime: no
  8.                                               PreEmptive                                                Lock
  9.        ID OSID        ThreadOBJ     State   GC     GC Alloc Context                  Domain           Count APT Exception
  10.    0    1 5588 00000000009d4510      a020 Enabled  00000000030387d0:000000000303a510 00000000009cb1d0     1 MTA
  11.    2    2 64b4 00000000009dc4d0      b220 Enabled  0000000000000000:0000000000000000 00000000009cb1d0     0 MTA (Finalizer)
  12.    3    3 4ddc 0000000000a1a010   180b220 Enabled  0000000002fe1e28:0000000002fe2450 00000000009cb1d0     0 MTA (Threadpool Worker)
  13.    4    4 6a94 0000000000a1d590   180b220 Enabled  0000000002fe73c8:0000000002fe8450 00000000009cb1d0     0 MTA (Threadpool Worker)
  14.    5    5 43ec 0000000000a7bbd0   180b220 Enabled  0000000002fec968:0000000002fee450 00000000009cb1d0     0 MTA (Threadpool Worker)
  15.    6    6 8fdc 0000000000a892b0   180b220 Enabled  0000000002ff0968:0000000002ff2450 00000000009cb1d0     0 MTA (Threadpool Worker)
  16.    7    7 4954 0000000000aa3270   180b220 Enabled  0000000002fee968:0000000002ff0450 00000000009cb1d0     0 MTA (Threadpool Worker)
  17.    8    8 5af4 0000000000a97eb0   180b220 Enabled  0000000002fe8968:0000000002fea450 00000000009cb1d0     0 MTA (Threadpool Worker)
  18.    9    9 4740 0000000000a99400   180b220 Enabled  0000000002fe0358:0000000002fe0450 00000000009cb1d0     0 MTA (Threadpool Worker)
  19.   10    a 6c38 0000000000a9f3a0   180b220 Enabled  0000000002fe3e28:0000000002fe4450 00000000009cb1d0     0 MTA (Threadpool Worker)
复制代码
  1. 0:012> !runaway
  2. User Mode Time
  3.   Thread       Time
  4.    0:5588      0 days 0:00:05.085
  5.    7:4954      0 days 0:00:01.903
  6.    3:4ddc      0 days 0:00:01.825
  7.    8:5af4      0 days 0:00:01.809
  8.    9:4740      0 days 0:00:01.747
  9.   10:6c38      0 days 0:00:01.731
  10.    4:6a94      0 days 0:00:01.700
  11.    5:43ec      0 days 0:00:01.622
  12.    6:8fdc      0 days 0:00:01.606
  13.   12:1e64      0 days 0:00:00.000
  14.   11:6a4       0 days 0:00:00.000
  15.    2:64b4      0 days 0:00:00.000
  16.    1:69e4      0 days 0:00:00.000
  17. [b]!mdt 00000000027736b8 看下,把这四个地址都看下:
  18. [/b]
复制代码
  1. 1   public class Consumer1
  2. 2     {
  3. 3         private string connString;
  4. 4         public Consumer1(string str)
  5. 5         {
  6. 6             this.connString = str;
  7. 7         }
  8. 8     }
  9. 9
  10. 10     public class Consumer2
  11. 11     {
  12. 12         private string connString;
  13. 13         public Consumer2(string str)
  14. 14         {
  15. 15             this.connString = str;
  16. 16         }
  17. 17     }
  18. 18
  19. 19     class Program
  20. 20     {
  21. 21         private static Consumer1 consumer1;
  22. 22         private static Consumer2 consumer2;
  23. 23
  24. 24         static void Main(string[] args)
  25. 25         {
  26. 26             consumer1 = new Consumer1("Conn1");
  27. 27             consumer2 = new Consumer2("Conn2");
  28. 28
  29. 29             Thread thread = new Thread(Proc);
  30. 30             thread.Start();
  31. 31              
  32. 32             lock (consumer2)
  33. 33             {
  34. 34                 Console.WriteLine("Proc->Lock consumer2");
  35. 35                 Thread.Sleep(1000);
  36. 36                 lock (consumer1)
  37. 37                 {
  38. 38                     Console.WriteLine("Proc->Lock consumer2->Lock consumer1 ");
  39. 39                 }
  40. 40             }
  41. 41
  42. 42         }
  43. 43
  44. 44         private static void Proc()
  45. 45         {
  46. 46             lock (consumer1)
  47. 47             {
  48. 48                 Console.WriteLine("Proc->Lock consumer1");
  49. 49                 Thread.Sleep(1000);
  50. 50                 lock (consumer2)
  51. 51                 {
  52. 52                     Console.WriteLine("Proc->Lock consumer1->Lock consumer2 ");
  53. 53                 }
  54. 54             }
  55. 55
  56. 56         }
  57. 57     }
复制代码
  1. 1 0:000> !dlk
  2. 2 Examining SyncBlocks...
  3. 3 Scanning for ReaderWriterLock instances...
  4. 4 Scanning for holders of ReaderWriterLock locks...
  5. 5 Scanning for ReaderWriterLockSlim instances...
  6. 6 Scanning for holders of ReaderWriterLockSlim locks...
  7. 7 Examining CriticalSections...
  8. 8 Scanning for threads waiting on SyncBlocks...
  9. 9 *** WARNING: Unable to verify checksum for D:\Test\PInvoke\CPP\Test\bin\Debug\Test.exe
  10. 10 Scanning for threads waiting on ReaderWriterLock locks...
  11. 11 Scanning for threads waiting on ReaderWriterLocksSlim locks...
  12. 12 Scanning for threads waiting on CriticalSections...
  13. 13 *DEADLOCK DETECTED*
  14. 14 CLR thread 0x3 holds the lock on SyncBlock 0000000000c94690 OBJ:00000000027736b8[Test.Consumer1]
  15. 15 ...and is waiting for the lock on SyncBlock 0000000000c946d8 OBJ:00000000027736d0[Test.Consumer2]
  16. 16 CLR thread 0x1 holds the lock on SyncBlock 0000000000c946d8 OBJ:00000000027736d0[Test.Consumer2]
  17. 17 ...and is waiting for the lock on SyncBlock 0000000000c94690 OBJ:00000000027736b8[Test.Consumer1]
  18. 18 CLR Thread 0x3 is waiting at Test.Program.Proc()(+0x31 IL,+0x98 Native) [D:\Test\PInvoke\CPP\Test\Program.cs @ 60,17]
  19. 19 CLR Thread 0x1 is waiting at Test.Program.Main(System.String[])(+0x68 IL,+0x196 Native) [D:\Test\PInvoke\CPP\Test\Program.cs @ 46,17]
  20. 20
  21. 21
  22. 22 1 deadlock detected.
复制代码
  1. 0000000000c94690 OBJ:00000000027736b8<br>
复制代码
  1. 0000000000c946d8 OBJ:00000000027736d0<br>
复制代码
  1. 0000000000c946d8 OBJ:00000000027736d0
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册