内存泄漏问题分析之非托管资源泄漏( 二 )


对于应用创建的大多数对象,可以依赖 .NET 垃圾回收器来进行内存管理 。但是,如果创建包含非托管资源的对象,则当你使用完非托管资源后,必须显式释放这些资源 。最常用的非托管资源类型是包装操作系统资源的对象,如文件、窗口、网络连接或数据库连接 。虽然垃圾回收器可以跟踪封装非托管资源的对象的生存期,但无法了解如何发布并清理这些非托管资源 。
虽然已经定位到通讯服务对于socket的处理不当,但是非托管资源到底是因为未能显式执行dispose方法导致的问题,还是说这些对象一直被引用而无法被回收?想要对于非托管资源的问题进行详细分析,可以使用 !finalizequeue命令进行分析 。该命令有三个可选参数:
  • -detail:显示需要清理的任何 SyncBlocks 的额外信息,以及有关等待清理的任何 RuntimeCallableWrappers (RCW) 的额外信息,这个选项也是默认值 。
  • -allReady:选项显示所有准备终止的对象,无论它们已被垃圾回收标记成这样,还是将被下一个垃圾回收标记 。“准备终止”列表中的对象为不再为根的可终止对象 。
  • -short:将输出限制为每个对象的地址,可以跟 -allReady或者 -detail一起使用 。
首先输入 !finalizequeue-allready检查有多少可以回收的对象:
  1. 0:000> !finalizequeue -allready
  2. SyncBlocks to be cleaned up: 0
  3. Free-Threaded Interfaces to be released: 0
  4. MTA Interfaces to be released: 0
  5. STA Interfaces to be released: 0
  6. ----------------------------------
  7. generation 0 has 71 finalizable objects (190ce568->190ce684)
  8. generation 1 has 32 finalizable objects (190ce4e8->190ce568)
  9. generation 2 has 56598 finalizable objects (19097090->190ce4e8)
  10. Finalizable but not rooted:976186dc 97619774 9761981c 97619844 9da920c8 9da920e0 9da9213c 9da92150
  11. ……
  12. Ready for finalization 0 objects (190ce684->190ce684)
  13. Statistics for all finalizable objects that are no longer rooted:
  14. MTCountTotalSize Class Name
  15. 6c3711b8116 System.Threading.Gen2GcCallback
  16. 6c36b328224 System.Threading.TimerHolder
  17. 6b68c0fc124 System.Net.Sockets.TcpClient
  18. 6b671fec140 System.Net.Sockets.NetworkStream
  19. 6b68105c8160 System.Net.SafeCloseSocket+InnerSafeCloseSocket
  20. 6b6811a88192 System.Net.SafeCloseSocket
  21. 6c35e2cc4208 System.Threading.Thread
  22. 67b788b84208 System.Windows.Forms.Control+ThreadMethodEntry
  23. 00d8a37c4336 **************.NetCommunicator.SocketConnectionInfo
  24. 6b690e804400 System.Net.Sockets.AcceptOverlappedAsyncResult
  25. 6b680f2c20400 System.Net.SafeNativeOverlapped
  26. 6c362a1821420 Microsoft.Win32.SafeHandles.SafeWaitHandle
  27. 6b67156420480 System.Net.Sockets.OverlappedCache
  28. 6b674f289828 System.Net.Sockets.Socket
  29. 6c36207c1071284 System.WeakReference
  30. 6b671800999900 System.Net.Sockets.OverlappedAsyncResult
  31. Total 313 objects
从这个结果可以看到只有9个对象是没有根引用可以直接回收的,这说明其他的一万多个socket都是有root引用而造成内存无法释放 。根引用是什么?在垃圾回收过程中起到什么作用?

推荐阅读