一 基础知识
0000000000c946d8 OBJ:00000000027736d0在分析之前,先上一张图:
从上面可以看到,这个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.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. !do 103b3360
看看103b3360地址的string包含哪些内容
可见,103b3360地址的字符串value="System.Web.UI.PageRequestManager:AsyncPostBackError", 占120bytes. 这个字符串对象包含3个字段,它们的偏移量分别是4,8,12。
5. dd 103b3360
看看103b3360的值
从左往右第一列是地址,而第二列开始则是地址上的数据。
6. !dumpheap -type String -min 100
看看堆上所有大于100字节的字符串。 注意:假如 -min 85000(大于85000字节的字符串或对象将存储在大对象堆上).0000000000c946d8 OBJ:00000000027736d0
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
- 1 public class LeakTest
- 2 {
- 3 private static string leakString;
- 4
- 5 public LeakTest()
- 6 {
- 7 for (int i = 0; i < 1000; i++)
- 8 {
- 9 leakString += "LEAK";
- 10 }
- 11 }
- 12
- 13 public string GetRamdonString()
- 14 {
- 15 System.Random random = new System.Random();
- 16
- 17 string str = string.Empty;
- 18 for (int i = 0; i < 25; i++)
- 19 {
- 20 str += str + random.Next(100);
- 21 }
- 22 return str;
- 23 }
- 24
- 25 public void NoDispose()
- 26 {
- 27 string str = GetRamdonString();
- 28
- 29 ZipFile zip = new ZipFile();
- 30 zip.AddEntry("a.txt", str);
- 31 zip.AddEntry("b.txt", str);
- 32 zip.Save("test.rar");
- 33 //zip.Dispose();
- 34 }
- 35 }
- 36
- 37 class Program
- 38 {
- 39 static void Main(string[] args)
- 40 {
- 41 LeakTest leakTest = new LeakTest();
- 42 leakTest.NoDispose();
- 43 Console.ReadLine();
- 44 }
- 45 }
复制代码 View Code0000000000c946d8 OBJ:00000000027736d0
需要说明的是:
这里程序里面定义了一个Static 字符串,及使用了Ionic.Zip 这个Zip压缩包,仅仅是为了模拟内存堆积现象,没有调用zip.Dispose()方法,事实上Ionic.Zip并不会造成内存泄露。
0000000000c946d8 OBJ:00000000027736d0
正式开始了:
啊哈,好极了。 运行程序,好家伙,果然很耗费内存! 这么个小程序,吃了287M,并启动了12个线程.
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 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.Dictionary`2+ValueCollection[[System.String, mscorlib],[Ionic.Zip.ZipEntry, Ionic.Zip.Reduced]]
- 7 000007ff000534f0 1 24 ZipTest.LeakTest
- 8 000007fee951e8e8 1 24 System.IO.TextReader+NullTextReader
- 9 000007fee94f8198 1 24 System.Security.Cryptography.RNGCryptoServiceProvider
- <br>11 ...<br>43 000007ff001d9130 1041 66624 Ionic.Zlib.DeflateManager+CompressFunc
- 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
复制代码 0000000000c946d8 OBJ:00000000027736d0
0000000000c946d8 OBJ:00000000027736d0
果然,我们看到了里面有2类大对象,分别占用了134M和138M . 好家伙!
0:005> !dumpheap -mt0000000000c946d8 OBJ:00000000027736d0
0000000000c946d8 OBJ:00000000027736d0- 1 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 0000000002ba4790- 1 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
复制代码 0000000000c946d8 OBJ:00000000027736d0
哦。这是个一维的数组,有65566字节,推测应该好像是short(int16)长度。
继续,
!gcroot 0000000002b42dd0- 0: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.List`1[[Ionic.Zlib.WorkItem, Ionic.Zip.Reduced]])->
- 000000000294ac38(System.Object[])->
- 0000000002b32d78(Ionic.Zlib.WorkItem)->
- 0000000002b42dd0(System.Byte[])
- ...
- 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[])
换一个看看:- 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.List`1[[Ionic.Zlib.WorkItem, Ionic.Zip.Reduced]])->
- 000000000294ac38(System.Object[])->
- 00000000029ac6d8(Ionic.Zlib.WorkItem)->
- 00000000029bc730(System.Byte[])
- ...
- 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- 0: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 objects
复制代码 Next,
0:012> !do 00000000025c26e0- 0: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....<br>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 <<
复制代码 View Code瞧准了,这是个主线程,他在等待Console.ReadLine(). 所以占用了这么长时间。
0000000000c946d8 OBJ:00000000027736d0
再在看一下这13个线程里,哪些是托管堆线程:
!threads- 0: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)
复制代码 在托管堆上启动的线程有10个。这10个线程分别是什么,继续看:
0号MTA: 程序主线程
MTA (Finalizer):这个是Finalizer线程,该线程负责垃圾对象回收。
MTA (Threadpool Worker):这些是ThreadPool创建的线程,这里是Ionic.Zlib.WorkItem产生的工作线程。
另外,CLR根据需要还会开启其他一些线程,如:
并发的GC线程 ,服务器GC线程 ,调试器帮助线程 ,AppDomain卸载线程 等.
0000000000c946d8 OBJ:00000000027736d0
看一下同步块情况,有么有死锁?
!syncblk
!dlk- (C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
- String: LEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKL....<br>EAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAKLEAK
- 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 案例分析
这个案例很简单,上菜:
- 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 public LeakTest()
- 2 {
- 3 for (int i = 0; i < 1000; i++)
- 4 {
- 5 leakString += "LEAK";
- 6 }
- 7 }
复制代码 只需敲一个命令,死锁就检测到了。 注意下面这些地址:- 0:012> !runaway
- User Mode Time
- Thread Time
- 0:5588 0 days 0:00:05.085
- 7:4954 0 days 0:00:01.903
- 3:4ddc 0 days 0:00:01.825
- 8:5af4 0 days 0:00:01.809
- 9:4740 0 days 0:00:01.747
- 10:6c38 0 days 0:00:01.731
- 4:6a94 0 days 0:00:01.700
- 5:43ec 0 days 0:00:01.622
- 6:8fdc 0 days 0:00:01.606
- 12:1e64 0 days 0:00:00.000
- 11:6a4 0 days 0:00:00.000
- 2:64b4 0 days 0:00:00.000
- 1:69e4 0 days 0:00:00.000
复制代码- 0:012> ~0s
- ntdll!ZwRequestWaitReplyPort+0xa:
- 00000000`77b714da c3 ret
- 0:000> !ClrStack -a
- OS Thread Id: 0x5588 (0)
- *** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v2.0.50727_64\mscorlib\c3beeeb6432f004b419859ea007087f1\mscorlib.ni.dll
- Child-SP RetAddr Call Site
- 00000000001de670 000007fee9b02c79 DomainNeutralILStubClass.IL_STUB(Microsoft.Win32.SafeHandles.SafeFileHandle, Byte*, Int32, Int32 ByRef, IntPtr)
- PARAMETERS:
- <no data>
- <no data>
- <no data>
- <no data>
- <no data>
- 00000000001de790 000007fee9b02d92 System.IO.__ConsoleStream.ReadFileNative(Microsoft.Win32.SafeHandles.SafeFileHandle, Byte[], Int32, Int32, Int32, Int32 ByRef)
- PARAMETERS:
- hFile = <no data>
- bytes = <no data>
- offset = <no data>
- count = <no data>
- mustBeZero = <no data>
- errorCode = 0x00000000001de820
- LOCALS:
- <no data>
- 0x00000000001de7c0 = 0x0000000000000000
- <no data>
- <no data>
- 00000000001de7f0 000007fee93f08da System.IO.__ConsoleStream.Read(Byte[], Int32, Int32)
- PARAMETERS:
- this = <no data>
- buffer = <no data>
- offset = <no data>
- count = <no data>
- LOCALS:
- 0x00000000001de820 = 0x0000000000000000
- <no data>
- 00000000001de850 000007fee9412a8a System.IO.StreamReader.ReadBuffer()
- PARAMETERS:
- this = <no data>
- LOCALS:
- <no data>
- 00000000001de8a0 000007fee9b0622f System.IO.StreamReader.ReadLine()
- PARAMETERS:
- this = <no data>
- LOCALS:
- <no data>
- <no data>
- <no data>
- <no data>
- 00000000001de8f0 000007ff00190188 System.IO.TextReader+SyncTextReader.ReadLine()
- PARAMETERS:
- this = 0x00000000030387b0
- 00000000001de950 000007feea23c6a2 ZipTest.Program.Main(System.String[])
- PARAMETERS:
- args = 0x00000000027e2680
- LOCALS:
- 0x00000000001de970 = 0x00000000027e26a0
复制代码- 0:012> !threads
- ThreadCount: 10
- UnstartedThread: 0
- BackgroundThread: 9
- PendingThread: 0
- DeadThread: 0
- Hosted Runtime: no
- PreEmptive Lock
- ID OSID ThreadOBJ State GC GC Alloc Context Domain Count APT Exception
- 0 1 5588 00000000009d4510 a020 Enabled 00000000030387d0:000000000303a510 00000000009cb1d0 1 MTA
- 2 2 64b4 00000000009dc4d0 b220 Enabled 0000000000000000:0000000000000000 00000000009cb1d0 0 MTA (Finalizer)
- 3 3 4ddc 0000000000a1a010 180b220 Enabled 0000000002fe1e28:0000000002fe2450 00000000009cb1d0 0 MTA (Threadpool Worker)
- 4 4 6a94 0000000000a1d590 180b220 Enabled 0000000002fe73c8:0000000002fe8450 00000000009cb1d0 0 MTA (Threadpool Worker)
- 5 5 43ec 0000000000a7bbd0 180b220 Enabled 0000000002fec968:0000000002fee450 00000000009cb1d0 0 MTA (Threadpool Worker)
- 6 6 8fdc 0000000000a892b0 180b220 Enabled 0000000002ff0968:0000000002ff2450 00000000009cb1d0 0 MTA (Threadpool Worker)
- 7 7 4954 0000000000aa3270 180b220 Enabled 0000000002fee968:0000000002ff0450 00000000009cb1d0 0 MTA (Threadpool Worker)
- 8 8 5af4 0000000000a97eb0 180b220 Enabled 0000000002fe8968:0000000002fea450 00000000009cb1d0 0 MTA (Threadpool Worker)
- 9 9 4740 0000000000a99400 180b220 Enabled 0000000002fe0358:0000000002fe0450 00000000009cb1d0 0 MTA (Threadpool Worker)
- 10 a 6c38 0000000000a9f3a0 180b220 Enabled 0000000002fe3e28:0000000002fe4450 00000000009cb1d0 0 MTA (Threadpool Worker)
复制代码- 0:012> !runaway
- User Mode Time
- Thread Time
- 0:5588 0 days 0:00:05.085
- 7:4954 0 days 0:00:01.903
- 3:4ddc 0 days 0:00:01.825
- 8:5af4 0 days 0:00:01.809
- 9:4740 0 days 0:00:01.747
- 10:6c38 0 days 0:00:01.731
- 4:6a94 0 days 0:00:01.700
- 5:43ec 0 days 0:00:01.622
- 6:8fdc 0 days 0:00:01.606
- 12:1e64 0 days 0:00:00.000
- 11:6a4 0 days 0:00:00.000
- 2:64b4 0 days 0:00:00.000
- 1:69e4 0 days 0:00:00.000
- [b]!mdt 00000000027736b8 看下,把这四个地址都看下:
- [/b]
复制代码- 1 public class Consumer1
- 2 {
- 3 private string connString;
- 4 public Consumer1(string str)
- 5 {
- 6 this.connString = str;
- 7 }
- 8 }
- 9
- 10 public class Consumer2
- 11 {
- 12 private string connString;
- 13 public Consumer2(string str)
- 14 {
- 15 this.connString = str;
- 16 }
- 17 }
- 18
- 19 class Program
- 20 {
- 21 private static Consumer1 consumer1;
- 22 private static Consumer2 consumer2;
- 23
- 24 static void Main(string[] args)
- 25 {
- 26 consumer1 = new Consumer1("Conn1");
- 27 consumer2 = new Consumer2("Conn2");
- 28
- 29 Thread thread = new Thread(Proc);
- 30 thread.Start();
- 31
- 32 lock (consumer2)
- 33 {
- 34 Console.WriteLine("Proc->Lock consumer2");
- 35 Thread.Sleep(1000);
- 36 lock (consumer1)
- 37 {
- 38 Console.WriteLine("Proc->Lock consumer2->Lock consumer1 ");
- 39 }
- 40 }
- 41
- 42 }
- 43
- 44 private static void Proc()
- 45 {
- 46 lock (consumer1)
- 47 {
- 48 Console.WriteLine("Proc->Lock consumer1");
- 49 Thread.Sleep(1000);
- 50 lock (consumer2)
- 51 {
- 52 Console.WriteLine("Proc->Lock consumer1->Lock consumer2 ");
- 53 }
- 54 }
- 55
- 56 }
- 57 }
复制代码- 1 0:000> !dlk
- 2 Examining SyncBlocks...
- 3 Scanning for ReaderWriterLock instances...
- 4 Scanning for holders of ReaderWriterLock locks...
- 5 Scanning for ReaderWriterLockSlim instances...
- 6 Scanning for holders of ReaderWriterLockSlim locks...
- 7 Examining CriticalSections...
- 8 Scanning for threads waiting on SyncBlocks...
- 9 *** WARNING: Unable to verify checksum for D:\Test\PInvoke\CPP\Test\bin\Debug\Test.exe
- 10 Scanning for threads waiting on ReaderWriterLock locks...
- 11 Scanning for threads waiting on ReaderWriterLocksSlim locks...
- 12 Scanning for threads waiting on CriticalSections...
- 13 *DEADLOCK DETECTED*
- 14 CLR thread 0x3 holds the lock on SyncBlock 0000000000c94690 OBJ:00000000027736b8[Test.Consumer1]
- 15 ...and is waiting for the lock on SyncBlock 0000000000c946d8 OBJ:00000000027736d0[Test.Consumer2]
- 16 CLR thread 0x1 holds the lock on SyncBlock 0000000000c946d8 OBJ:00000000027736d0[Test.Consumer2]
- 17 ...and is waiting for the lock on SyncBlock 0000000000c94690 OBJ:00000000027736b8[Test.Consumer1]
- 18 CLR Thread 0x3 is waiting at Test.Program.Proc()(+0x31 IL,+0x98 Native) [D:\Test\PInvoke\CPP\Test\Program.cs @ 60,17]
- 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
- 21
- 22 1 deadlock detected.
复制代码- 0000000000c94690 OBJ:00000000027736b8<br>
复制代码- 0000000000c946d8 OBJ:00000000027736d0<br>
复制代码- 0000000000c946d8 OBJ:00000000027736d0
复制代码 来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |